小程序canvas输出gif格式的图片作为表情

canvas的基础直接略过,可以自己去学习,我们主要看小程序输出gif格式的方式

1.可以使用前端传参的方式,通过后端去处理图片完成(此处不讲解)

2.使用微信的FileSystemManager输出gif格式图片

在看微信小程序的官方文档当中我们可以知道canvas使用wx.canvasToTempFilePath的API输出两种图片的格式是png和jpg,那么我们需要如何实现gif格式的输出

我们需要使用gif.js;官网地址:gif.js,因为小程序不直接操作DOM的属性和只能有一个worker的方式,我们需要改写gif.js的文件

GIF.prototype.finishRendering = function() {
                    var data, frame, i, image, j, k, l, len, len1, len2, len3, offset, page, ref, ref1, ref2;
                    len = 0;
                    ref = this.imageParts;
                    for (j = 0,
                    len1 = ref.length; j < len1; j++) {
                        frame = ref[j];
                        len += (frame.data.length - 1) * frame.pageSize + frame.cursor
                    }
                    len += frame.pageSize - frame.cursor;
                    this.log("rendering finished - filesize " + Math.round(len / 1e3) + "kb");
                    data = new Uint8Array(len);
                    offset = 0;
                    ref1 = this.imageParts;
                    for (k = 0,
                    len2 = ref1.length; k < len2; k++) {
                        frame = ref1[k];
                        ref2 = frame.data;
                        for (i = l = 0,
                        len3 = ref2.length; l < len3; i = ++l) {
                            page = ref2[i];
                            // data.set(page, offset);
                            for (var _i = 0; _i < frame.pageSize; _i++) {
                                data[offset + _i] = page[_i]
                            }
                            if (i === frame.data.length - 1) {
                                offset += frame.cursor
                            } else {
                                offset += frame.pageSize
                            }
                        }
                    }
                    let worker = this.freeWorkers.shift();
                    // console.log('worker', worker)
                    worker.terminate(); // 销毁多线程
                    // image = new Blob([data],{
                    //     type: "image/gif"
                    // });
                    return this.emit("finished", data)
                    // return this.emit("finished", image, data)
                }
GIF.prototype.addFrame = function(image, options) {
                    var frame = {}, key;
                    if (options == null) {
                        options = {}
                    }
                    frame.index = options.index || 0;
                    frame.transparent = this.options.transparent;
                    for (key in frameDefaults) {
                        frame[key] = options[key] || frameDefaults[key]
                    }
                    if (this.options.width == null) {
                        this.setOption("width", image.width)
                    }
                    if (this.options.height == null) {
                        this.setOption("height", image.height)
                    }
                    if (image && image.width && image.height && image.data) {
                        frame.data = image.data
                    // } else if (typeof ImageData !== "undefined" && ImageData !== null && image instanceof ImageData) {
                    //     frame.data = image.data
                    // } else if (typeof CanvasRenderingContext2D !== "undefined" && CanvasRenderingContext2D !== null && image instanceof CanvasRenderingContext2D || typeof WebGLRenderingContext !== "undefined" && WebGLRenderingContext !== null && image instanceof WebGLRenderingContext) {
                    //     if (options.copy) {
                    //         frame.data = this.getContextData(image)
                    //     } else {
                    //         frame.context = image
                    //     }
                    // } else if (image.childNodes != null) {
                    //     if (options.copy) {
                    //         frame.data = this.getImageData(image)
                    //     } else {
                    //         frame.image = image
                    //     }
                    } else {
                        throw new Error("Invalid image")
                    }
                    return this.frames.push(frame)
                }

第二步:

    async createGif()  
        const self = this
        if (this.isShown) {
            return
        } 
        this.isShown = true
        let systemObj = wx.getSystemInfoSync()
        let pixelRatio = systemObj.pixelRatio
        this.setData({
            pixelRatio: pixelRatio
        })
        let windowWidth = systemObj.windowWidth // 总的px宽度
        let _1rpx = windowWidth / 750.0
    
        let width = this.data.imgW, 
            height = this.data.imgH
        let ctx = wx.createCanvasContext('ca')
        let gif = new GIF({
            workers: 1,
            width: width/pixelRatio, // 输出图片的宽高
            height: height/pixelRatio,
            debug: true
        })

        let startTime
        gif.on('start', function() {
            startTime = Date.now()
            return true
        });
        gif.on('progress', function(p) {
            self.setData({
                progress: p * 100
            })
            return true
        });
        gif.on('finished', function(data) {
            const fm = wx.getFileSystemManager()
            let ab = new ArrayBuffer(data.length) // js方法
            let dv = new DataView(ab) // js方法
            for (var i = 0; i < data.length; i++) {
                dv.setInt8(i, data[i])
            }
            fm.writeFile({
                filePath: `${wx.env.USER_DATA_PATH}/test.gif`,
                encoding: 'binary',
                data: ab,
                success (r) {
                    console.log('保存图片', `${wx.env.USER_DATA_PATH}/test.gif`)
                    self.setData({
                        gifFile: `${wx.env.USER_DATA_PATH}/test.gif`
                    })
                },
                fail (r) {
                    console.log(r)
                }
            })
            return true
        });
        ctx.clearRect(0, 0, width/pixelRatio, height/pixelRatio)
        ctx.setFillStyle('#f00');
        ctx.fillRect(0, 0, width/pixelRatio, height/pixelRatio)
        ctx.save()
        ctx.drawImage(this.data.diyFile,0,0, width/pixelRatio, height/pixelRatio)
        let drawRes = await new Promise(r => ctx.draw(true, r))
        try {
            let imgdata = await new Promise((resolve, reject) => wx.canvasGetImageData({
                canvasId: 'ca',
                height: height/pixelRatio,
                width: width/pixelRatio,
                x: 0,
                y: 0,
                success (r) {
                    resolve(r)
                },
                fail (e) {
                    reject(e)
                }
            }))
            console.log(imgdata)
            setTimeout(()=>{
                gif.addFrame(imgdata, {delay: 2000})
                console.log(gif.render())
            }, 2000)
        } catch(e) {

        }
}

这样我们就改写好了适合小程序的gif图,后面根据gif的官方文档API添加图片即可,实际上我们只需要了解小程序跟PC端的DOM操作的区别然后对应修改gif.js的文件即可,有时间的可以扩展在小程序当中生成gif动画功能

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值