前端项目记录:用gifuct-js实现控制gif图播放速度

文章讲述了作者在项目中遇到需求,需要播放并控制GIF动图的速度。开始尝试使用libgif库,但发现其功能有限。后来转向自行解析GIF,最终找到并利用gifuct-js库,通过解析GIF的ArrayBuffer实现逐帧绘制,实现在Vue项目中对GIF的灵活操控。
摘要由CSDN通过智能技术生成

公司项目需求,播放gif动图,并且要能控制播放速度,在网上搜索了一下gif相关的库,首先搜到了libgif,这个库基于jQuery,使用起来比较麻烦,而且主要的功能是控制gif图的播放和暂停,没有逐帧播放的功能。

于是选择从文件本身入手,尝试自己解析gif图,前端可以获取gif文件的ArrayBuffer信息,然后对其进行分析,gif图的编码遵循的原则可以参考网站:What's In A GIF

解析了半天,发现太麻烦了,又去找有没有已经实现的库,找到了gifuct-js,主要功能是获取gif图的ArrayBuffer,解析出颜色、大小、图片等信息并返回一个对象。

对象结构如下(摘自官网)

{
    // The color table lookup index for each pixel
    pixels: [...],
    // the dimensions of the gif frame (see disposal method)
    dims: {
        top: 0,
        left: 10,
        width: 100,
        height: 50
    },
    // the time in milliseconds that this frame should be shown
    delay: 50,
    // the disposal method (see below)
    disposalType: 1,
    // an array of colors that the pixel data points to
    colorTable: [...],
    // An optional color index that represents transparency (see below)
    transparentIndex: 33,
    // Uint8ClampedArray color converted patch information for drawing
    patch: [...]
 }

github项目链接:GitHub - matt-way/gifuct-js: Fastest javascript .GIF decoder/parser

在项目的demo.js里面给出了一些案例,gifuct-js解析完色卡和图片之后,将图片逐帧绘制到canvas上,从而实现对gif图片的灵活操控。

代码

<template>
    <div>
        <canvas ref="gifNode"></canvas>
    </div>
</template>
<script>
import { parseGIF, decompressFrames } from 'gifuct-js';
export default {
    name: 'MyGif',
    created: function () {
        
    },
    data: function () {
        return {
            width: 300, // 画板宽度
            height: 300, // 画板高度
            // 页面上的canvas的上下文
            gifCanvasCtx: null,
            // 用于绘制gif单张图片的画板及上下文
            tempCanvas: null,
            tempCanvasCtx: null,
            // 用于存放正在播放的gif信息
            currentGifFrames: null,
            // 记录gif图播放速度
            speed: 5,
            // 记录正在播放的gif图的序号
            count: 0,
            // 用来存放图片数据信息
            frameImageData: null,
            // 绘制图像用的定时器
            gifPlayTimer: null
        };
    },
    mounted() {
        this.init();
    },
    methods: {
        async init() {

            // 设置画板
            let canvas = this.$refs.gifNode;
            canvas.width = this.width;
            canvas.height = this.height;
            this.gifCanvasCtx = canvas.getContext('2d');
            // 初始化
            this.tempCanvas = document.createElement('canvas');
            this.tempCanvasCtx = this.tempCanvas.getContext('2d');

             // getFile用来向服务器请求文件并返回ArrayBuffer
            gifFrames = await getFile('test.gif');
            this.resetGifPlayer();
        },
        // 当修改速度的时候,重置gif播放器
        resetGifPlayer(speed) {
            clearInterval(this.gifPlayTimer);
            this.gifPlayTimer = null;
            this.gifPlayTimer = setInterval(() => {
                this.drawGif(this.currentGifFrames[this.count]);
                this.count++;
            }, this.speed);
        },
        // 利用gifuct.js库逐帧绘制gif图像
        drawGif(frame) {
            if (!frame) {
                this.count = 0;
                return;
            }
            if (frame.disposalType === 2) {
                this.gifCanvasCtx.clearRect(0, 0, this.width, this.height);
            }
            let dims = frame.dims;
            if (!this.frameImageData || dims.width != this.frameImageData.width || dims.height != this.frameImageData.height) {
                this.tempCanvas.width = dims.width
                this.tempCanvas.height = dims.height
                this.frameImageData = this.tempCanvasCtx.createImageData(dims.width, dims.height)
            }

            this.frameImageData.data.set(frame.patch)
            this.tempCanvasCtx.putImageData(this.frameImageData, 0, 0)

            this.gifCanvasCtx.drawImage(this.tempCanvas, dims.left, dims.top, this.width, this.height)
        },

    }
};
</script>
<style scoped>
</style>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值