图片切换Slider

作者: mirror 日期: -

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默认比例,不符合该比例的图片,效果有差异.

End Line