如何仅清除Canvas指定区域,实现轮播滑动时保留上一张图片内容
优化方案
你当前的性能瓶颈来自于不必要的全屏清空和全量重绘上一张内容,针对横向滑入的轮播场景,有以下几个层级的优化方案:
方案1:取消无意义的全屏清空与全量重绘(性能提升最明显)
你的场景中上一张图片本身已经完整绘制在画布上,滑动过程中0到head区间的内容完全不需要修改,完全不需要每次清空画布再重绘整张上一张图,只需要逐帧绘制新图片滑入的增量区域即可:
// 优化后的draw2示例 function draw2() { if (head > 0) { const step = 10; head = head - step; // 去掉全屏清空、去掉上一张图的全量重绘 // 只绘制当前帧新滑入的新图区域 ctx.fillStyle = "rgba(255, 0, 255,1)"; ctx.fillRect(head, 0, step, canvas.height); // 每次只画新增的step宽度,不用画整张新图 window.requestAnimationFrame(draw2); } }
这个方案下每帧只需要绘制步长宽度的内容,渲染开销是原来的几十分之一,第一张图的滑入逻辑draw1也可以用同样的思路优化。
方案2:离屏Canvas缓存静态内容(适用于更复杂的滑动场景)
如果你的轮播存在双向滑动、半透明叠加、多元素叠加等复杂场景,无法用增量绘制实现,可以提前把上一张图的内容缓存到离屏Canvas中,后续直接调用drawImage绘制缓存内容,比每次重绘路径、图片资源的开销低很多,因为drawImage是GPU加速的光栅化内容绘制:
// 初始化离屏Canvas const offscreenCanvas = document.createElement('canvas'); const offscreenCtx = offscreenCanvas.getContext('2d'); offscreenCanvas.width = canvas.width; offscreenCanvas.height = canvas.height; // 上一张图绘制完成后,缓存到离屏Canvas offscreenCtx.drawImage(canvas, 0, 0); // 动画帧内绘制缓存 function draw2() { if (head > 0) { head = head - 10; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(offscreenCanvas, 0, 0); // 直接绘制缓存,性能远高于重绘整张原图 ctx.fillStyle = "rgba(255, 0, 255,1)"; ctx.fillRect(head, 0, canvas.width - head, canvas.height); window.requestAnimationFrame(draw2); } }
方案3:局部清空画布
如果因为业务逻辑必须清空画布,也不要清空整个画布,只清空需要修改的区域即可,减少清空操作的开销:
// 只清空本次需要重绘的右半区域,不用清全屏 ctx.clearRect(head, 0, canvas.width - head + 10, canvas.height);
内容的提问来源于stack exchange,提问作者user16971617
相关产品推荐
相关产品推荐

