组件 gif-mock

介绍:

通过在canvas中播放序列静态图片,达到跟播放gif动图类似的效果。

缘由:

  1. gif图限制,gif图无法实现半透明效果的,要么是透明要么不透明,导致一些效果无法实现,例如光影效果
  2. 微信小程序限制,目前发现能实现背景透明的视频为webm以及mov,但是尝试webm发现,微信小程序的背景是黑色的(在浏览器中为透明)

引用:

{
  "usingComponents": {
    "gif-mock": "/components/gif-mock/index"
  }
}

使用:

<gif-mock src="{{imgUrl}}vip/coupon/{{theme.name}}/s4/#index.png" pic-count="20" bindload="onStartBgLoadEnd"></gif-mock>

下面是相关代码,可以复制保存为指定文件即可

index.wxml

<!--components/gif-mock/index.wxml-->
<canvas id="output" type="2d" style="width:{{width * dpr}}rpx;height:{{height * dpr}}rpx; display: inline-block;"></canvas>
<view hidden="true">
  <image src="{{item.remoteSrc}}" wx:for="{{remoteSrcItems}}" wx:for-index="idx" wx:for-item="item" wx:key="idx" bindload="onImageLoadEnd" data-idx='{{item.idx}}' ></image>
</view>

index.js

// components/gif-mock/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    width: { // 属性名
      type: Number,
      value: 300
    },
    height: { // 属性名
      type: Number,
      value: 300
    },
    interval: {
      type: Number,
      value: 80
    },
    src: {
      type: String,
      value: ''
    },
    picCount: {
      type: Number,
      value: 0
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    remoteSrcItems: []
  },
  intervalHandler: null,
  lifetimes: {
    attached() {
      var that = this;
      var dpr = wx.getSystemInfoSync().pixelRatio;
      that.setData({
        dpr: dpr
      });
      this.data.remoteSrcItems.length = 0;
      for (var i = 0; i < this.data.picCount; i++) {
        var remoteSrc = that.data.src.replace(/#index/g, i + 1);
        console.log(remoteSrc)
        this.data.remoteSrcItems.push({
          idx: i,
          remoteSrc: remoteSrc,
          loading: true
        });
      }
      that.setData({
        remoteSrcItems: this.data.remoteSrcItems
      });
    },
    detached: function () {
      // 在组件实例被从页面节点树移除时执行
      clearInterval(this.intervalHandler);
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    onImageLoadEnd(e) {
      console.log(e);
      this.data.remoteSrcItems[e.currentTarget.dataset.idx].loading = false;
      this.checkLoadEnd();
    },
    checkLoadEnd() {
      for (var i = 0; i < this.data.picCount; i++) {
        if (this.data.remoteSrcItems[i].loading) {
          return;
        }
      }
      this.triggerEvent("load");
      this.play();
    },
    play() {
      var that = this;
      if (this.intervalHandler) {
        return;
      }
      wx.createSelectorQuery().in(this).select('#output')
        .fields({
          node: true,
          size: true
        })
        .exec((res2) => {
          // 如果没有指定Id的元素,res2将为null
          console.log("abc", res2)
          if (!res2 || res2.length <= 0) {
            return;
          }
          var canvas = res2[0].node;
          const output = canvas.getContext('2d')
          var dpr = that.data.dpr;
          console.log('canvas', canvas, dpr)
          canvas.width = that.data.width * dpr
          canvas.height = that.data.height * dpr
          // output.scale(dpr, dpr)
          console.log(canvas);

          var i = 0;
          this.intervalHandler = setInterval(() => {
            var remoteSrc = that.data.remoteSrcItems[i].remoteSrc;
            // console.log(remoteSrc)
            i = i >= (this.data.picCount - 1) ? 0 : i + 1;
            let img = canvas.createImage(); //创建img对象
            img.onload = () => {
              output.clearRect(0, 0, canvas.width, canvas.height)
              output.drawImage(img, 0, 0, canvas.width, canvas.height); //drawImage(要绘画的元素, x轴, y轴)
            };
            img.src = remoteSrc;
          }, that.data.interval);
        });
    }
  }
})