为什么使用cloneNode创建多个音频文件会阻止我控制音频源的属性,以及如何覆盖此属性

问题描述

我现在有一段时间从事网络游戏制作,我很快注意到,一旦我使用.cloneNode(true)多次播放相同的音频文件,以避免每次我想通过amd重新下载文件播放音频文件时,我松懈了诸如回放音量和回放速率之类的事情,有人知道我如何才能为音频文件的每个副本重新获得那些参数的变量吗?

我尝试设置原始文件中音频副本的参数,但是没有果汁

In the HTML : 
<audio src = "sight.wav" id="sight"/>
<button onclick="playSound()">Play some audio</audio>

In the Js
var get = new Function("id","return document.getElementById(id)");

function playSound()
{
  get(sight).volume = 0.30;
  get(sight).playbackRate = 0.40;
  get(sight).cloneNode(true).play();
};

对我来说似乎是有效的代码,但是就像我说的,没有麻烦,cloneNodes完全忽略了音量和播放设置,只播放普通音频。我该怎么办?

解决方法

Node.cloneNode()在元素上调用时,将创建一个与原始Node具有相同属性的相同子类型的新Element。

在这里,您不是在修改原始文档的attributes,而是仅修改了一些IDL属性,这些属性不会被反映,因此也不会被克隆。

const original = document.querySelector("audio");
console.log( "default",[...original.attributes].map( (att) => att.name ) ); // []
original.volume = 0.2;
console.log( "volume set",[...original.attributes].map( (att) => att.name ) ); // []
original.controls = true;
console.log( "controls set",[...original.attributes].map( (att) => att.name ) ); // [ "controls" ]

const clone = original.cloneNode();
console.log( "clone volume",clone.volume ); // 1
console.log( "clone controls",clone.controls ); // true
<audio></audio>

因此,您可以重写代码,以便设置克隆元素的volumeplayBackRate而不是设置原始节点的元素,但是请注意,如果您确实产生了多个相同的音频,您应该使用Web-Audio API及其AudioBuffer interface来提供对这些媒体播放时间的更大控制,并且比初始化DOM MediaElement占用的内存少得多。