为什么我的程序 运行 在 atom-html-preview 中,而 atom-live-server 在 Atom 中但不在 Chrome 中,也不在 JSFiddle 中?

Why is my program running in atom-html-preview and atom-live-server inside Atom but not in Chrome nor in JSFiddle?

我有一个程序使用网络音频 API 来可视化音频的时域波形。它在 Atom 中运行良好,我使用“harmsk”的“atom-html-preview”包,但它在 Chrome 或 JSFiddle 中没有 运行。

我做错了什么?是语法错误还是我使用了过时的函数?

编辑:它也适用于“jas-chen”的“atom-live-server”

在 Atom 中,输出看起来像 this

let frequencyArray = [];
let analyser;
let request;
var flag=0;
var height=0;

const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
const bars = Math.round(canvas.width);
const lineWidth = 3;


var centerX = canvas.width / 2;
var centerY = canvas.height / 2;


const audio = new Audio();
audio.src =
  "https://s3.us-west-2.amazonaws.com/storycreator.uploads/ck9kpb5ss0xf90132mgf8z893?client_id=d8976b195733c213f3ead34a2d95d1c1";
audio.crossOrigin = "anonymous";
audio.load();

const context = new (window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
const source = context.createMediaElementSource(audio);

source.connect(analyser);
analyser.connect(context.destination);

frequencyArray = new Uint8Array(analyser.frequencyBinCount);


  function begin()
  {
    audio.play();
    requestAnimationFrame(drawCanvas);
  };

  function end()
  {
    cancelAnimationFrame(request);
    audio.pause();
  };

audio.addEventListener("ended", close);

function close()
{
  if(flag==0)
  {
    flag=1;
  }
  else
  {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      flag=0;
  }
}


  const drawCanvas = () => {

      ctx.clearRect(0, 0, canvas.width, canvas.height);
      analyser.getByteTimeDomainData(frequencyArray);

      for (var i = 0; i < bars; i+=5) {
       height = frequencyArray[i] * 0.25;

        drawLine(
          {
            i,
            bars,
            height
          },
          canvas,
          ctx
        );
      }

      if(flag==0)
      {
      request = requestAnimationFrame(drawCanvas);
      }
      else
      {
        flag=2;
        close();
      }
  };

  
  const drawLine = (opts, canvas, ctx) => {
    const { i, bars, height } = opts;

    // draw the bar
    ctx.strokeStyle = "#212121";
    ctx.lineWidth = lineWidth;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(i, centerY);
    ctx.lineTo(i, centerY + height);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(i, centerY);
    ctx.lineTo(i, centerY - height);
    ctx.stroke();


};
<!DOCTYPE html>
<html>
<head>

<body>

<button onClick=begin()>Start</button>
<button onClick=end()>End</button>
<canvas id="myCanvas" width="500" height="200" style="border:1px solid #d3d3d3;">
</canvas>


</body>
</html>

我猜是因为这个错误,在控制台中

js:47 The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

如果您引用邮件中的link,则指定

If you create your AudioContext on page load, you’ll have to call resume() at some time after the user interacted with the page (e.g., user clicked a button). Alternatively, the AudioContext will be resumed after a user gesture if start() is called on any attached node.

由于您的 AudioContext 是在用户手势(点击)之前创建的,您可以修改 begin 函数以恢复上下文,

  function begin()
  {
    context.resume().then(() => {
          audio.play();
          requestAnimationFrame(drawCanvas);
    });
  };

工作演示:

let frequencyArray = [];
let analyser;
let request;
var flag=0;
var height=0;

const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
const bars = Math.round(canvas.width);
const lineWidth = 3;


var centerX = canvas.width / 2;
var centerY = canvas.height / 2;


const audio = new Audio();
audio.src =
  "https://s3.us-west-2.amazonaws.com/storycreator.uploads/ck9kpb5ss0xf90132mgf8z893?client_id=d8976b195733c213f3ead34a2d95d1c1";
audio.crossOrigin = "anonymous";
audio.load();

const context = new (window.AudioContext || window.webkitAudioContext)();
analyser = context.createAnalyser();
const source = context.createMediaElementSource(audio);

source.connect(analyser);
analyser.connect(context.destination);

frequencyArray = new Uint8Array(analyser.frequencyBinCount);


  function begin()
  {
    context.resume().then(() => {
     audio.play();
     requestAnimationFrame(drawCanvas);
    })
  };

  function end()
  {
    cancelAnimationFrame(request);
    audio.pause();
  };

audio.addEventListener("ended", close);

function close()
{
  if(flag==0)
  {
    flag=1;
  }
  else
  {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      flag=0;
  }
}


  const drawCanvas = () => {

      ctx.clearRect(0, 0, canvas.width, canvas.height);
      analyser.getByteTimeDomainData(frequencyArray);

      for (var i = 0; i < bars; i+=5) {
       height = frequencyArray[i] * 0.25;

        drawLine(
          {
            i,
            bars,
            height
          },
          canvas,
          ctx
        );
      }

      if(flag==0)
      {
      request = requestAnimationFrame(drawCanvas);
      }
      else
      {
        flag=2;
        close();
      }
  };

  
  const drawLine = (opts, canvas, ctx) => {
    const { i, bars, height } = opts;

    // draw the bar
    ctx.strokeStyle = "#212121";
    ctx.lineWidth = lineWidth;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(i, centerY);
    ctx.lineTo(i, centerY + height);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(i, centerY);
    ctx.lineTo(i, centerY - height);
    ctx.stroke();


};
<!DOCTYPE html>
<html>
<head>

<body>

<button onClick=begin()>Start</button>
<button onClick=end()>End</button>
<canvas id="myCanvas" width="500" height="200" style="border:1px solid #d3d3d3;">
</canvas>


</body>
</html>