前边都是废话,直接从第四段开始看
对于一些html的动画页面,canvas动画页面,会需要大量的图片文件。一张一张的从服务器获取图片,会影响页面的显示。
怎样提高动画的效果,可以写一个load页面,然后通过js把图片先从服务器加载下来,避免在动画的时候,保证动画的流畅性。但是问题来了,在有大量图片的页面里,需要大量的请求数,在前端优化里就有提到要减少请求数,雪碧图很好,但是每次都要找设计给你拼好,当然,自己花点时间也是可以掌握这个东西,去做。但是有没有一种程序的方式,把图片整合,然后运用呢,重点来了,往下看。
图片基本上都是一些二进制数据的拼接,对我要整合的就是这些二进制数据。前提知识点,nodejs(不需要很多)中的文件操作就是 fs 了,文件的读、写。接下来就是js中的 API ArrayBuffer,还有他的两个视图TypedArray和DataView。还有blob,都用的比较浅,我本人也是初接触这些。
压缩阶段: 通过nodejs来进行压缩,很好的一点通过nodejs的 fs 读取到的文件是一个buffer数据。在前端用过js可以完美解析
由于nodejs读取文件的一个便利性,所以压缩主要是,读取文件然后设置文件的存储规则,我的文件基本是每个图片包括四部分: 图片名称的大小(指字节数)+图片名称+图片文件的大小+图片的二进制文件,前边三部分通过Uint32来存储,存储方式是一个默认的小端字节序。
上代码:
var fs = require('fs'); //所要读取文件的所在的位置 文件夹 var pat = './img/'; //生成文件的保存位置与文件名,文件后缀可以任意 var create = './cgppt/cg.sw'; var buffer = new Buffer(0); var files = fs.readdirSync(pat); var count = files.length; files.forEach(function(filename) { count--; //读取文件数据 var text = fs.readFileSync(pat + filename); //将文件的名称以及数据等信息压缩在一起 var headerBuffer = header(filename, text); if(!!headerBuffer) { //将不同文件的二进制数据合并在一起,并写入文件 buffer = Buffer.concat([buffer, headerBuffer]); if(count == 0) { fs.writeFile(create, buffer, (err) => { if (err) throw err; console.log('It\'s saved!'); }); } } }); function header(filename, data) { //整合单个文件数据 var text = fs.readFileSync(pat + filename); var fileLen = numToBuffer(filename.length + 4); if(filename.search(/\.png$|\.jpg$/ig) != -1) { var file = strToBuffer('img/' + filename); var dataLen = numToBuffer(text.length); var data = new Buffer(text); var header = Buffer.concat([fileLen, file, dataLen, data]); return header; } return false; } function strToBuffer(data) { //文件名称等信息规则 var buffer = new Buffer(0); var str = data.toString(); for(let i = str.length - 1; i >= 0; i--) { var num = str.charCodeAt(i); var strBuffer = numToBuffer(num); buffer = Buffer.concat([strBuffer, buffer]); } return buffer; } function numToBuffer(num) { //以小端字节序方式将文件大小信息编入 var buffer = new Buffer(4), ppp = []; ppp[0] = num % 256; ppp[1] = num % (256*256) / 256; ppp[2] = num / (256*256) % (256); ppp[3] = num / (256*256*256); for (var i = 0; i < buffer.length; i++) { buffer[i] = ppp[i]; } return buffer; }
前端解析: 这里就是通过js来解析这个二进制文件,将通过blob和URL生成的一个链接赋值给img的src,也可以用于canvas动画
关键代码
while(len < data.byteLength) { //获取文件名的长度 var f = data.getUint32(len, !0); len += 4; var l = ''; //读取文件名 for(var c = 0; c< f; c++) { var h = data.getUint32(len, !1); len += 4; l += String.fromCharCode(h); } //读取文件的长度 var p = data.getUint32(len, !0); len += 4; //读取文件 var d = new Uint8Array(buffer, len, p); //obj为文件名->文件的一个对象 obj[l] = d; len += p, //文件名数组 o.push(l), //文件数组 a.push(d) }
本文的大部分要点都来自于 阮一峰老师的JavaScript标准参考教程,还有MDN的web技术文档。
本人前端小白,如有问题还请指正
欢迎转载、交流
参考链接: 阮一峰 二进制数据、阮一峰 nodejs fs模块、阮一峰 二进制数组