css 在画布上使用透明图像的逐帧动画效果不佳

jgwigjjp  于 2023-03-09  发布在  其他
关注(0)|答案(1)|浏览(125)

如何消除口吃效果?

  • 画布是否只能在下一帧“就绪”时才能清除?

这个演示只在屏幕滚动时有效(所以我建议在小预览中查看)。而且,滞后问题在这里的预览中似乎没有那么严重。但是在Chrome中,图像偶尔会消失几毫秒/帧--让画布完全透明。

const html = document.documentElement;
const canvas = document.getElementById("prodPicAnimation");
const context = canvas.getContext("2d");

const frameCount = 120;
const currentFrame = index => (
  `https://www.dr-adler.com/content/produkte/Sheabutter/renderAnimation/${index.toString().padStart(3, '0')}.png`
)

const preloadImages = () => {
  for (let i = 1; i < frameCount; i++) {
    const img = new Image();
    img.src = currentFrame(i);
  }
};

const img = new Image()
img.src = currentFrame(1);

canvas.width=750;
canvas.height=750;

img.onload=function(){
  context.drawImage(img, 0, 0);
}

const updateImage = index => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  img.src = currentFrame(index);
  context.drawImage(img, 0, 0);
}

window.addEventListener('scroll', () => {  
  const scrollTop = html.scrollTop;
  const maxScrollTop = 750;
  const scrollFraction = scrollTop / maxScrollTop;
  const frameIndex = Math.min(
    frameCount - 1,
    Math.ceil(scrollFraction * frameCount)
  );
  
  requestAnimationFrame(() => updateImage(frameIndex + 1))
});

preloadImages()
<canvas id="prodPicAnimation"></canvas>
eqfvzcg8

eqfvzcg81#

我不确定这是否与drawImage/clearRect的速度有关。我认为这是替换图像src的争用条件。下面是一个没有任何滚动问题的解决方案,它预加载并预创建数组中的所有img标记。https://codepen.io/andrewray/pen/poOwmNb?editors=1010

const html = document.documentElement;
const canvas = document.getElementById("prodPicAnimation");
const context = canvas.getContext("2d");

const frameCount = 120;
const imageUrls = new Array(frameCount).fill(0).map((_, index) =>
  `https://www.dr-adler.com/content/produkte/Sheabutter/renderAnimation/${(index + 1).toString().padStart(3, '0')}.png`
);

console.log(imageUrls);

const preloadImage = async (src) => {
  return new Promise(resolve => {
    var img = new Image();
    img.onload = function() { resolve(img); }
    img.src = src;
  })
}

const preloadImages = () => Promise.all(imageUrls.map(url => preloadImage(url)));

canvas.width=750;
canvas.height=750;

const updateImage = img => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.drawImage(img, 0, 0);
}

const init = async () => {
  const images = await preloadImages();
  document.getElementById('loading').remove();
  console.log('Ready', images[0]);
  updateImage(images[0]);
  window.addEventListener('scroll', () => {
    const scrollTop = html.scrollTop;
    const maxScrollTop = 750;
    const scrollFraction = scrollTop / maxScrollTop;
    const frameIndex = Math.min(
      frameCount - 1,
      Math.ceil(scrollFraction * frameCount)
    );

    requestAnimationFrame(() => updateImage(images[frameIndex]))
  });
}
init();

相关问题