HTML5 Canvas图片轮播新增滑入过渡效果运行异常问题求助
Canvas图片轮播滑入过渡效果实现方案
原有代码问题
- 仅维护单张图片实例,无法同时存储上一张和待切换的新图,不满足底层保留旧图的需求
- 每次渲染前全量清除画布,直接清空了上一张图片的渲染内容
- 无逐帧过渡动画逻辑,切换为直接跳转,无法实现滑入效果
- 采用setTimeout控制渲染时序,动画流畅度低,且图片加载时序容易出问题
修复后完整代码
var pathToYourImages = [ "images/image1.png", "images/image2.png", "images/image3.jpg", "images/image4.jpg", ]; var canvas = null; var ctx = null; // 预加载所有图片存储 var images = []; var currentIndex = 0; // 过渡相关变量 var isTransitioning = false; var prevImage = null; var currentImage = null; var offsetX = 0; var speed = 5; // 滑入速度,数值越大速度越快 var INTERVAL = 3000; // 每张图停留时长,单位毫秒 var x=0; var y=0; var scale=0; window.onload = function() { canvas = document.getElementById('myCanvas'); ctx = canvas.getContext('2d'); // 先预加载所有图片 preloadImages().then(() => { currentImage = images[currentIndex]; scaleToFit(currentImage); render(); // 启动轮播定时器 setInterval(startTransition, INTERVAL); }) }; // 图片预加载函数 function preloadImages() { let loadCount = 0; return new Promise(resolve => { pathToYourImages.forEach((src, index) => { let img = new Image(); img.src = src; img.onload = () => { images[index] = img; loadCount++; if(loadCount === pathToYourImages.length) { resolve(); } } }) }) } function scaleToFit(img) { scale = Math.min(canvas.width / img.width, canvas.height / img.height); x = (canvas.width / 2) - (img.width / 2) * scale; y = (canvas.height / 2) - (img.height / 2) * scale; } // 启动过渡动画 function startTransition() { if(isTransitioning) return; isTransitioning = true; prevImage = images[currentIndex]; // 计算下一张图索引 currentIndex = (currentIndex + 1) % pathToYourImages.length; currentImage = images[currentIndex]; scaleToFit(currentImage); offsetX = canvas.width; // 新图初始从画布右侧外开始滑入 // 启动帧动画 requestAnimationFrame(animateTransition); } // 过渡动画逐帧逻辑 function animateTransition() { // 先绘制底层的上一张图,不用清画布 scaleToFit(prevImage); ctx.drawImage(prevImage, x, y, prevImage.width * scale, prevImage.height * scale); // 绘制滑入的新图 scaleToFit(currentImage); ctx.drawImage(currentImage, x + offsetX, y, currentImage.width * scale, currentImage.height * scale); // 偏移量递减 offsetX -= speed; if(offsetX <= 0) { // 过渡完成 isTransitioning = false; offsetX = 0; render(); return; } requestAnimationFrame(animateTransition); } // 正常渲染静态图 function render(){ ctx.clearRect(0,0,canvas.width,canvas.height); ctx.drawImage(currentImage, x, y, currentImage.width * scale, currentImage.height * scale); }
效果说明
- 过渡过程中旧图始终保留在底层,新图从右侧平滑滑入覆盖,完全符合需求
- 提前预加载所有图片,避免切换时出现加载空白
- 采用requestAnimationFrame实现动画,流畅度远高于原setTimeout方案
- 可根据需要修改speed参数调整滑入速度,修改INTERVAL参数调整每张图片的停留时长
内容的提问来源于stack exchange,提问作者Talha
相关产品推荐
相关产品推荐

