javascript - 使 Canvas 动画异步

标签 javascript html animation canvas css-animations

以下代码是一个更大项目的一部分:

<body>
  <canvas id="check" width="35px" height="40px" style="background-color: blue;"></canvas>
</body>
<script>
  const check = document.getElementById('check');
  const checkCtx = check.getContext('2d');
  check.onclick = function() {
    drawCheck(checkCtx, 5, 30);
    setTimeout(function() {
      fadeOut(check);
    }, 1000);
    setTimeout(function() {
      check.style.opacity = "1";
      checkCtx.clearRect(0, 0, check.width, check.height);
    }, 2000);
    check.style.backgroundColor = "blue";
  }

  function drawCheck(ctx, x, y) {
    var x1 = x;
    var y1 = y;
    var x2 = x1;
    var y2 = y1;
    var x3 = x1 + 14;
    var y3 = y1 + 7;
    ctx.beginPath();
    ctx.strokeStyle = "green";
    ctx.lineCap = "round";
    ctx.lineWidth = 5;
    ctx.moveTo(x1, y1);

    function draw() {
      x2++;
      y2 += .5;
      ctx.lineTo(x2, y2);
      ctx.stroke();
      if (x2 < x1 + 14) {
        requestAnimationFrame(draw);
      } else {
        function drawNext() {
          x3 += .5;
          y3 -= 1.5;
          ctx.lineTo(x3, y3);
          ctx.stroke();
          if (x3 < x1 + 24) {
            requestAnimationFrame(drawNext);
          } else {
            return;
          }
        }
        drawNext();
        return;
      }
    }
    draw();
  }

  function fadeOut(obj) {
    var opc = 1;
    var finish = false;
    obj.style.opacity = 1;

    function fade() {
      opc -= 0.125;
      obj.style.opacity = opc + "";
      console.log(opc);
      if (opc > 0) {
        requestAnimationFrame(fade);
      }
    }
    console.log("Wait for it...");
    fade();
    console.log("Finished!");
  }
</script>

如果您查看控制台,您可以看到 fadeOut 函数在 fade 函数结束之前结束。因此,我必须使用多个 setTimeout 函数。我的其他功能也有同样的问题。我不想依赖这些,那么如何让代码等待被调用的函数返回?

最佳答案

回调(ES5)、 promise (ES6)、异步/等待(ES7)

您想要异步运行代码。这意味着等待部分代码完成工作后再运行下一个。默认情况下,Javascript 会尽快执行所有操作,无论如何。

错误:

function run(){ 
  console.log('1: start run')
  setTimeout(()=>{
    console.log('2: timeout')
  },1000)
}

function run2(){
  console.log('3: start run2')
  setTimeout(()=>{
    console.log('4: timeout')
  },1000) // change time here and check order console.log's
}

function run3(){
  console.log('4: start run3')
  setTimeout(()=>{
    console.log('5: timeout')
  },1000)
}
run()
run2()
run3()

3 个函数同时启动,它们给出结果,而无需查看其他 2 个函数中发生的情况。尝试更改超时以更改 conole.log 中的顺序。但在现实生活中,您无法像这里一样控制时间执行。

回调:

通过回调,您可以将一个函数嵌套在另一个函数中,并将其作为参数传递。想法是在第二个函数开始之前等待第一个函数执行...在第三个函数之前等待第二个函数...依此类推。

function runWithCallback(callback){ // run1
  console.log('1: start runWithCallback()')
  setTimeout(()=>{
    console.log('2: timeout')
    callback(runAfterCallback)
  },1000)
}

function runCallback(callback){ // run2
  console.log("3: start runCallback()")
  setTimeout(()=>{
    console.log('4: timeout')
    callback()
  },1000)
}

function runAfterCallback(){ // run3
  console.log("5: start runAfterCallback()")
  setTimeout(()=>{
    console.log('6: timeout')
    // next call back here if needed
  },1000)
}

runWithCallback(runCallback)

现在,无论每个函数的执行时间有多长,下一个函数都会在第一个函数完成后开始。这样您就不需要猜测执行时间来延迟代码。

promise

在 es6 中,你可以使用 Promise 来做到这一点,这有点像回调的语法糖。在撰写本文时,Promise 的浏览器覆盖率达到 90% https://caniuse.com/#feat=promises

function run1(){
  console.log('1: run1')
  return new Promise(function(resolve){
    console.log('2: promise')
    setTimeout(resolve,100)
  })
}

function callback(){
  console.log('3: run2 callback')
  return new Promise(function(resolve){
    console.log('4: promise')
    setTimeout(resolve, 1000)
  })
}

function callback2(){
  console.log('5: run3 callback')
  return new Promise(function(resolve){
    console.log('6: promise')
    setTimeout(resolve, 100)
  })
}

run1()
  .then(callback()) // try to change order here, uncoment last lines...
  .then(callback2())
  // .then(callback2())
  // .then(callback())

关于javascript - 使 Canvas 动画异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50776240/

相关文章:

ios - 自定义动画过渡不适用于 iPhone 7 模拟器

javascript - 如何使用 io-ts 验证数组长度?

c# - SignalR 差异

javascript - 在 JavaScript 中导入 Excel 文件

css - 动画图标在关键帧期间向左移动

swift - 在 Swift 的 UIKit Dynamics 中,如何定义一个圆边界来包含一个 UIView?

javascript - 如何将 datetimepicker 与 ASP.NET 本地化集成

javascript - ajax(PHP 和 Javascript)出现问题 - 如何正确传输?

javascript - 在每个节点上应用 onmouseover - GOjs 库 - 泳道

javascript - 如何在滚动条上应用 css?