last update 2025/06/18
用canvas做图片切换,用到 drawImage() 这个API.
切换的本质是将图片用各种办法画到canvas上,在每种画法之间切换.图片画到canvas上是基于宽度等比缩放的,高度的超出部分将截断.
html结构是一个容器DIV,里面有多个IMG,容器的长宽比例要设置为图片的长宽比.
图片是隐藏的,在容器中存放,一组图片的比例需要一致.支持动态添加图片.
<div class="slider" id="sliderBox"> <img src="slider1.jpg" class="d-none"/> <img src="slider2.jpg" class="d-none"/> <img src="slider3.jpg" class="d-none"/> <img src="slider4.jpg" class="d-none"/> <img src="slider5.jpg" class="d-none"/> <img src="slider6.jpg" class="d-none"/> // 会加入canvas对象,图片就是画在这个对象上的. </div>
// slider对象 // object let slid = {}; slid.boxId = boxId;// 图片容器divId slid.whScale = whScale || (1 / 1);// 容器长宽比例,设置为图片比例 slid.ctx = null; slid.imgs = null; slid.img = null;// 当前执行动画的图片 slid.imgIndex = 0;// 当前执行动画的图片索引 slid.skipTime = 2000; slid.aniArr = null; slid.aniIndex = 0; slid.bar = null;// 状态栏容器 // 等待加载图片完成后开始动画: 定时检查图片是否加载完成,加载中时,画面显示loading.加载完成后开始动画 slid.loadImgAndStart = (...index) => {} // 开始动画: 不会等待图片加载完成 slid.start = (...index) => {} // 每个动画是一个函数,新增动画时,添加一个函数.然后在 aniArr 数组中加入这个函数. function newAniFun(slider){} // 当前已有的动画,函数加入数组的顺序决定动画顺序 slid.aniArr = [fade, bothInMiddle, stripe, middleOpen, block, middleCir, left, top, leftZoom, rotate, middleCirScan];
// 动画函数示例模板: 图片从中心扩大显示 function middleCir(sld) { // 1.成员 let ctx = sld.ctx; let img = sld.img(); let r = 0, w = sld.w, h = sld.h, imgW = img.width, imgH = img.height; let scale = w / imgW, imgHScale = imgH * scale; // 2.动画函数 let step = (timestamp) => { // 结束动画条件 if (r > Math.max(w, h) * 0.707) { // 调用下一个动画 sld.next(); return; } ctx.save(); ctx.clearRect(0, 0, w, h); ctx.beginPath(); ctx.arc(w / 2, h / 2, r, 0, Math.PI * 2); ctx.clip(); ctx.drawImage(img, 0, 0, w, imgHScale); ctx.restore(); r++; window.requestAnimationFrame(step); } // 3.使用requestAnimationFrame()开始动画 window.requestAnimationFrame(step); }
// 使用方法,传入容器id,图片长宽比例. let slid = slider('sliderBox',whScale); // 定时检查容器中所有img加载完成后开始动画. // index:动画数组下标,可指定动画顺序. // 例如:0,1,2,2 表示依次执行0,1,2下标的3个动画,动画2会执行两次 slid.loadImgAndStart(...index); // 不检查加载情况,直接开始动画 slid.start(...index);
以下图片比例都不一样,容器使用1:1默认比例,不符合该比例的图片,效果有差异.