【问题标题】:Best way to have sequential Canvas Animations In Javascript在 Javascript 中具有顺序画布动画的最佳方法
【发布时间】:2022-01-07 14:37:04
【问题描述】:

所以我尝试使用 PaperJs 沿路径为画布元素(或在本例中为 PaperJs 路径/文本)设置动画(PaperJs 也是路径和元素的制作方式)。这种工作方式是我有一组用户创建的框架(当我说框架时,我的意思是从这里开始的这个用户创建的框架),其中有用户在其中绘制的 0-10 条路径。从这里我在一个位置创建一个数字,并将对该画布元素的引用存储在一个名为 text 的数组中,并将相应的路径存储在一个名为 paths 的数组中。对于每一帧,我附加的代码都与它的路径和文本列表一起运行。我的代码可以工作,但非常笨拙,并且我想添加的功能受到限制。问题是我希望能够调用一个函数 animate_frame(OBJ_WITH_PATHS[0]) 并让它为帧设置动画,然后一旦它完成了第一帧的动画调用 animate_frame(OBJ_WITH_PATHS[1]) 所以整个 OBJ 列表与路径按顺序进行动画处理。目前发生这种情况是因为该行

if ((event.time > frame_num*2) && (event.time < ((frame_num*2) + 2))) {.

需要此行的原因是程序使用 onFrame 事件为每一帧制作所有文本和路径,并且没有严格限制对象可见的时间和动画所有帧同时进行而不是通过框架(我的框架有路径)。这种行为是我将每帧的总时间严格限制为 2 秒的原因。我还应该注意我将填充颜色更改为黑色然后透明的原因,因此元素仅在动画期间可见,而不是在 2 秒动画周期之前或之后。我目前使用的相关代码如下所示

  var offset = [];

  for(let i = 0; i < paths.length; i ++) {
    offset[i] = 0;
  }
  var time_sec = 2;   
  for(let i = 0; i < paths.length; i ++) {
      text[i].onFrame = function (event) {
          var speed = paths[i].length/time_sec;
          if ((event.time > frame_num*2) && (event.time < ((frame_num*2) + 2))) {
              text[i].fillColor = "black";          
              if (offset[i] < paths[i].length){
                  text[i].position = paths[i].getPointAt(offset[i]);
                  offset[i] += event.delta*speed; // speed - 150px/second
               } else {
                  offset[i] = paths[i].length;
               }
          } else {
              text[i].fillColor = new paper.Color(0.5,0);
          }
      paper.view.draw();
    }
  }

我的代码限制了我想要添加的功能,例如

  • 暂停
  • 跳到下一帧/返回一帧
  • 播放帧(然后暂停,直到他们再次点击播放,然后播放单帧)
  • 可变速度(即一帧需要 2 秒,第二帧需要 4 秒)

我还想谈谈我已经尝试在调用 animate_frame 之间实现等待 2 秒,但是来自 PaperJS 的 onFrame(event) 在此等待期间不会发生,因此它不起作用),我还尝试了一个标志 var 和一个while循环,但这也不起作用。

所以我想知道是否有更好的方法来做到这一点。我喜欢创建一个动画对象,其中该对象包含要移动/动画的路径和画布元素,并且可以通过类似 animation.play(); 调用动画。然后它还可以等待上一个动画完成,这样我就可以拥有一组动画帧。对于整个项目,此时我已与 PaperJs 结婚,但我可以将路径位置数据放入常规 JS 数组并将其传递到新包中,如果有一个包可以在画布顶部设置动画元素适合我正在尝试做的事情。 感谢您的帮助/想法!

【问题讨论】:

    标签: javascript npm animation canvas paperjs


    【解决方案1】:

    对于复杂的动画场景,我建议您使用适当的动画库,这将使整个事情变得更容易。
    例如,GSAP 可能对所有播放/暂停...处理都有很大帮助。
    这是一个简单的 fiddle 演示如何使用它来控制基于 Paper.js 的动画。

    您应该能够使其适应您的特定用例。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Debug Paper.js</title>
        <script src="https://unpkg.com/acorn"></script>
        <script src="https://unpkg.com/paper"></script>
        <script src="https://unpkg.com/gsap"></script>
        <style>
            html,
            body {
                margin   : 0;
                overflow : hidden;
                height   : 100%;
            }
    
            canvas[resize] {
                width  : 100%;
                height : 100%;
            }
    
            #buttons {
                position : fixed;
                top      : 50px;
                left     : 50px;
                display  : flex;
                gap      : 15px;
            }
        </style>
    </head>
    <body>
    <div id="buttons">
        <button id="play">play</button>
        <button id="pause">pause</button>
        <button id="reverse">reverse</button>
    </div>
    <canvas id="canvas" resize></canvas>
    <script>
        paper.setup('canvas');
    
        const initialPosition = paper.view.center;
    
        const circle = new paper.Path.Circle({
            center: initialPosition,
            radius: 50,
            fillColor: 'orange'
        });
    
        function update(t) {
            circle.position = initialPosition.add([t * 100, 0]);
        }
    
        const obj = { value: 0 };
        var timeLine = gsap.timeline({
            onUpdate: (event) => {
                update(obj.value);
            }
        });
        timeLine.to(obj, { value: 1, duration: 1 });
        timeLine.pause();
    
        document.querySelector('#play').addEventListener('click', () => timeLine.play());
        document.querySelector('#pause').addEventListener('click', () => timeLine.pause());
        document.querySelector('#reverse').addEventListener('click', () => timeLine.reverse());
    </script>
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-27
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多