记一次使用apng动画两种方式

  1. apng-canvas
  2. apng-js

1. 使用apng-canvas做apng动画

使用起来代码简单,容易理解;但是监听动画的过程。

APNG

APNG 全称是 Animated Portable Network Graphics , 是 PNG 格式的动画扩展。APNG 的第1帧为标准PNG图像,剩余的动画和帧速等数据放在PNG扩展数据块里。这里有点类似于视频的关键帧,关键帧有完整的图像信息,而两个关键帧之间只保留了变化的信息。
简单来说,APNG 支持全彩和透明,无杂边问题.

但并不是所有软件都支持APNG。

Android上有APNG View等,iOS上有APNGKit

而Web上,Firfox和Safari是支持APNG,Chrome是支持WebP的。

所以我们要在Web上使用APNG可以使用Canvas

Canvas & APNG

我们可以使用 apng-canvas库。

举例
APNG.ifNeeded().then(function() {
    var images = document.querySelectorAll(".apng-image");
    for (var i = 0; i < images.length; i++) APNG.animateImage(images[i]);
});

APNG这个对象是apng-canvas这个库提供的,ifNeeded()函数是用来判断浏览器是否支持APNG。

APNG.animateImage()是需要传入一个 Image Element,之后就交给Canvas去处理了。

2. 使用apng-js做apng动画

注:底部有作者 apng.vue的组件源码作参考

apng-js

apng-js 官方demo

使用方式
import parseAPNG from 'apng-js';

const apng = parseAPNG(buffer);
if (apng instanceof Error) {
    // handle error
}
// work with apng object

parseAPNG的参数是一个ArrayBuffer类型,比起apng-canvas的使用要较为复杂一些。
在这里我就举一下我之前的做法:

我们需要的是加载本地和远端的apng图片来进行动画操作.

因为最终参数需要一个ArrayBuffer类型的,而我们只有一张图片的url,因此需要进行转换。
经过测试得出转换步骤如下:

  1. 先去请求这张图片以返回类型设为blob类型
// 加载图片资源,得到blob类型的值
loaderURL(url) {
  function createXmlHttpRequest() {
    if (window.ActiveXObject) {
      return new ActiveXObject('Microsoft.XMLHTTP');
    } else if (window.XMLHttpRequest) {
      return new XMLHttpRequest();
    }
  }
  return new Promise((resolve) => {
    let xhr = createXmlHttpRequest();
    xhr.open("get", url, true);
    xhr.responseType = "blob";
    xhr.onload = function (res) {
      if (this.status == 200) {
        var blob = this.response;
        resolve(blob);
      }
    }
    xhr.send();
  })
}
  1. 将blob转换成ArrayBuffer类型
// 将blob转换成buffer
blobToArrayBuffer(blob) {
  return new Promise((resolve) => {
    // Blob 转 ArrayBuffer
    let reader = new FileReader();
    reader.readAsArrayBuffer(blob);
    reader.onload = function() {
      console.log(reader.result)
      resolve(reader.result)
    }
  })
}
  1. 可以使用apng-js的parseAPNG得到apng对象,通过该对象可以获得动画播放器player
var apng = parseAPNG(buffer);
apng.getPlayer(canvas.getContent('2d')).then(player => {
    // 调用播放动画
    player.play();
})

player对象中有

  • play – playback started;
  • frame – frame played (frame number passed as event parameter);
  • pause – playback paused;
  • stop – playback stopped;
  • end – playback ended (for APNG with finite count of plays).
    通过官方文档可看出,我们可以监听整个动画的事件。
    官方demo中监听代码片段
    img

作者apng.vue源码

<template lang="pug">
  .apng-div(ref="apng-div" v-if="src")
    canvas(ref="apng-canvas")
</template>

<script>
// require('./../libs/apng-canvas.min.js')
import commonMixin from '@/mixins/commonMixin'
import parseAPNG from 'apng-js'

export default {
  mixins: [commonMixin],
  data() {
    return {
    }
  },

  props: {
    width: {
      type: String | Number,
      required: true
    },
    height: {
      type: String | Number,
      required: true
    },
    src: {
      type: String,
      required: true
    }
  },

  mounted() {
    let canvas = this.$refs['apng-canvas'];
    this.loaderURL(this.src).then(blob => {
      console.log(blob)

      this.blobToArrayBuffer(blob).then(arrayBuffer => {
        let apng = parseAPNG(arrayBuffer);
        canvas.width = apng.width;
        canvas.height = apng.height;
        let scale = this.width * this.remVal / apng.width
        canvas.style = 'zoom: ' + scale;
        apng.getPlayer(canvas.getContext('2d')).then(player => {
          player.play();
        })
      })
    })
  },
  methods: {
    calc(val) {
      return this.remVal * val;
    },
    blobToArrayBuffer(blob) {
      return new Promise((resolve) => {
        // Blob 转 ArrayBuffer
        let reader = new FileReader();
        reader.readAsArrayBuffer(blob);
        reader.onload = function() {
          console.log(reader.result)
          resolve(reader.result)
        }
      })
    },
    loaderURL(url) {
      function createXmlHttpRequest() {
        if (window.ActiveXObject) {
          return new ActiveXObject('Microsoft.XMLHTTP');
        } else if (window.XMLHttpRequest) {
          return new XMLHttpRequest();
        }
      }
      return new Promise((resolve) => {
        let xhr = createXmlHttpRequest();
        xhr.open("get", url, true);
        xhr.responseType = "blob";
        xhr.onload = function (res) {
          if (this.status == 200) {
            var blob = this.response;
            resolve(blob);
          }
        }
        xhr.send();
      })
    }
  }
}
</script>

<style lang="less" scoped>

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值