requestAnimationFrame序列执行问题:如何实现淡出后再淡入效果
问题:Canvas 淡出后淡入效果同时执行的解决方法
我想实现先淡出(fadeOut)再淡入(fadeIn)的效果,写了如下代码:
function fadeOut(content) { console.log('fade out'); alpha -= delta; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.globalAlpha = alpha; content(); if (alpha > 0) { requestAnimationFrame(fadeOut.bind(this, content)); } else { alpha = 1; ctx.globalAlpha = alpha; } } function fadeIn(content) { console.log('fade in'); alpha += delta; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.globalAlpha = alpha; content(); if (alpha < 1) { requestAnimationFrame(fadeIn.bind(this, content)); } else { alpha = 1; ctx.globalAlpha = alpha; } }
单独调用这两个函数都正常,但如果像下面这样用requestAnimationFrame依次调用,两个效果会同时执行:
requestAnimationFrame(fadeOut.bind(this, drawMap.bind(this, MAP1))); requestAnimationFrame(fadeIn.bind(this, drawMap.bind(this, MAP1)));
请问该怎么解决这个问题?
解决方案
你遇到的问题本质是:连续调用两次requestAnimationFrame会把两个动画函数同时加入浏览器的动画帧队列,它们会在后续的帧中并行执行,导致淡入和淡出效果重叠。
要实现严格的「先淡出再淡入」,必须在淡出动画完全结束的回调里触发淡入动画,具体修改如下:
步骤1:修改fadeOut函数,添加结束回调逻辑
在fadeOut的结束分支(alpha <= 0时),直接调用fadeIn的动画请求:
function fadeOut(content, fadeInContent) { console.log('fade out'); alpha -= delta; // 限制alpha最小值为0,避免出现负数 alpha = Math.max(alpha, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.globalAlpha = alpha; content(); if (alpha > 0) { requestAnimationFrame(fadeOut.bind(this, content, fadeInContent)); } else { // 淡出完成,立即启动淡入动画 requestAnimationFrame(fadeIn.bind(this, fadeInContent)); } }
步骤2:优化fadeIn函数的初始状态
为了避免状态残留,确保淡入从0开始:
function fadeIn(content) { console.log('fade in'); // 确保alpha从0开始递增 if (alpha <= 0) alpha = 0; alpha += delta; // 限制alpha最大值为1 alpha = Math.min(alpha, 1); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.globalAlpha = alpha; content(); if (alpha < 1) { requestAnimationFrame(fadeIn.bind(this, content)); } else { alpha = 1; ctx.globalAlpha = alpha; } }
步骤3:调用方式简化
现在只需要触发一次fadeOut,传入淡出和淡入要绘制的内容即可:
// 第一个参数:淡出时渲染的内容;第二个参数:淡入时渲染的内容 requestAnimationFrame(fadeOut.bind(this, drawMap.bind(this, MAP1), drawMap.bind(this, MAP1)));
这样就能保证两个动画严格按顺序执行,不会出现重叠的情况。
内容的提问来源于stack exchange,提问作者Dank391
相关产品推荐
相关产品推荐

