我试图将整个画布分成20个相等的列,并分别在y轴上设置动画。目标是创建类似于here的类似波形滚动动画。首先,我尝试使用php生成的带有文本的图像来创建wave滚动效果,并尝试在单个div中将其作为背景图像进行动画处理。从技术上讲它可以正常工作,但是性能和页面加载时间却非常糟糕。现在,我想用画布创建它:我已经在其中包含所有图像和文本的内容,并尝试对其进行动画处理。我试图用getImageData()将整个内容保存在列(矩形)中,然后用ImageData创建了创建的矩形,并以循环的方式重新绘制它们,但是性能仍然很糟糕,尤其是在移动设备上。动画循环如下所示:

var animate = function(index, y) {
  // The calculations required for the step function
  var start = new Date().getTime();
  var end = start + duration;
  var current = rectangles[index].y;
  var distance = y - current;
  var step = function() {
    // get our current progress
    var timestamp = new Date().getTime();
    var progress = Math.min((duration - (end - timestamp)) / duration, 1);
    context.clearRect(rectangles[index].x, rectangles[index].y, columnWidth, canvas.height);
    // update the rectangles y property
    rectangles[index].y = current + (distance * progress);
    context.putImageData(rectangles[index].imgData, rectangles[index].x, rectangles[index].y);
    // if animation hasn't finished, repeat the step.
    if (progress < 1)
      requestAnimationFrame(step);
  };
  // start the animation
  return step();
};


现在的问题是:如何将整个画布分成相等的列,并使其在y轴上具有良好的动画效果?有什么建议么?也许在Pixi.js / Greensock的帮助下?提前致谢!

最佳答案

不要使用getImageData和setImageData进行动画处理。画布是图像,可以像任何图像一样渲染。

做你想做的

创建画布的第二个副本,并使用该画布作为要渲染的条纹的来源。

例。



const slices = 20;
var widthStep;
var canvas = document.createElement("canvas");
var canvas1 = document.createElement("canvas");
canvas.style.position = "absolute";
canvas.style.top = canvas.style.left = "0px";

var ctx = canvas.getContext("2d");
var ctx1 = canvas1.getContext("2d");
var w = canvas.width;
var h = canvas.height;
function resize(){
    canvas.width = canvas1.width = innerWidth;
    canvas.height = canvas1.height = innerHeight;
    w = canvas.width;
    h = canvas.height;
    ctx1.font = "64px arial black";
    ctx1.textAlign = "center"
    ctx1.textBaseLine = "middle";
    ctx1.fillStyle = "blue";
    ctx1.fillRect(0,0,w,h);
    ctx1.fillStyle = "red";
    ctx1.fillRect(50,50,w-100,h-100);
    ctx1.fillStyle = "black";
    ctx1.strokeStyle = "white";
    ctx1.lineWidth = 5;
    ctx1.lineJoin = "round";
    ctx1.strokeText("Waves and canvas",w / 2, h / 2);
    ctx1.fillText("Waves and canvas",w / 2, h / 2);
    widthStep = Math.ceil(w / slices);
}
resize();
window.addEventListener("resize",resize);
document.body.appendChild(canvas);
function update(time){
    var y;
    var x = 0;
    ctx.clearRect(0,0,canvas.width,canvas.height);
    for(var i = 0; i < slices; i ++){
        y = Math.sin(time / 500 + i / 5) * (w / 8);
        y += Math.sin(time / 700 + i / 7) * (w / 13);
        y += Math.sin(time / 300 + i / 3) * (w / 17);
        ctx.drawImage(canvas1,x,0,widthStep,h,x,y,widthStep,h);
        x += widthStep;
     }
     requestAnimationFrame(update);
}
requestAnimationFrame(update);

08-28 04:02