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动画功能
demo可以扫描的二维码diy栏目查看效果
|