公司项目性能调优,要把小图标合成一张大图片,以减少服务器请求。也就是要制作传说中的CSS图像精灵。
上百张图片,美工mm在photoshop里一个个的拖,太慢太累。也不是很复杂的工作,不如写个程序来做吧。
看Demo点这里
思路
- 选择磁盘上的小图标,支持多选。
- 把选中的小图标一张张的绘制到
canvas上。
简单起见,纵向排列,每个小图标占一行,也就是最终canvas上绘制了老长老长的内容。 canvas导出png图片。
Show Me the Code
1. 支持多选的file input
<input type="file"
accept="image/gif,image/jpg,image/jpeg,image/png,image/bmp"
multiple>
type="file"指定该input为文件选择框accept限制可选文件类型multiple表示支持多选
2. 绘制图标到canvas上
canvas上绘制图片,要用到这个方法:
CanvasRenderingContext2d.drawImage(image, dx, dy)
- 参数
image是绘制到canvas上的元素
支持HTMLImageElement、SVGImageElement、HTMLCanvasElement等。
在这次的程序中,我传入的是一个HTMLImageElement,即dom元素img。 - 参数
dx指定小图标左上角在canvasX轴上的位置 - 参数
dy指定小图标左上角在canvasY轴上的位置
有了这个方法,我们就可以把一个
img元素绘制到canvas上了。但是怎么把fileInput选中的文件转成img元素呢?
读取选中的文件
fileInput选完文件后会触发change事件,事件监听器里,通过files属性可以得到选中的文件。
fileInput.addEventListener('change', () => {
let selectedFiles = fileInput.files;
...
});
这里要注意一下:
selectedFiles不是Array对象,而是FileList对象。
如果你想用Array的方法操作,例如想按文件名排个序什么的,可以用下面的方法将它转化为Array对象。
let selectedFiles = Array.prototype.slice.call(selectedFiles);
转化成img元素
要使用到FileReader去读取文件内容,以DataURL的形式输出,设置给img.src。
以selectedFiles中的一个File对象为例。
let fileReader = new FileReader();
let img = document.createElement('img');
fileReader.onload = () => {
img.src = fileReader.result;
img.onload = () => {
// onload触发以后才能读到img的宽和高
console.log(`${file.name}: ${img.width}px * ${img.height}`);
};
};
fileReader.readAsDataURL(file);
3.canvas导出图片
简单的话,chrome右键canvas->图片另存为...就可以了。
但这样不够直观,我想加一个导出图片的按钮。
首先来定义一个导出按钮。
<a id="exportBtn" class="button" download="compressed.png">导出图像精灵</a>
download="compressed.png"这个属性可以让链接点击后,下载文件,并且以compressed.png为文件名保存。
前面说到FileReader读取文件内容,可以以DataURL形式输出。
canvas.toDataURL(type, encoderOptions)也可以把canvas的内容以DataURL形式输出。
Canvas绘制完所有图标后,将DataURL设置给导出按钮的href即可。
exportBtn.href = canvas.toDataURL('png');
本文介绍了一种通过程序批量将小图标合成一张大图片的方法,用于减少网页加载时的HTTP请求次数。具体步骤包括:使用HTML5的file input选择多张图片、利用FileReader API读取图片并转换为DataURL格式、在Canvas上绘制这些图片以及最后导出合成后的精灵图。
349

被折叠的 条评论
为什么被折叠?



