You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 06:15:05