本篇主要涉及到:
- 文件上传
- 图片编辑
- 图片文件下载
一、文件上传
文件上传目前了解的主要有三种方式:
- type="file"的input输入框
- drop拖放事件;
- 另有"ctrl+V"进行粘贴,但是此方法使用有局限性,如:不支持windows系统文件的复制粘贴(大概理解为windows系统的粘贴只是对文件路径的引用)
1、input文件上传
html部分
<input id="fileInput" type="file" accept="image/png, image/jpeg">
// accept定义支持的文件类型
复制代码
js获取文件
$('#fileInput').on('change', function () {
fn(this.files[0]);
})
// this.files是一个文件集合,如果一次性上传多个文件相应就是this.files[0]、this.files[1]...
复制代码
2、drop拖放文件上传
html部分可以是一个div元素就行
<div class="dropBox" id="dropHere">
<p class="info">把文件拖放到这里</p>
<p class="info hide">你上传的文件是:<span id="fileName"></span></p>
</div>
复制代码
js操作部分需要对目标元素的ondragenter和ondragover进行阻止默认事件操作,防止浏览器直接打开文件
// 拖拽上传事件
function bandDropEvent (el,fn) {
el.ondragenter = function (event) { // 清除默认事件,防止浏览器直接打开图片文件
event.stopPropagation();
event.preventDefault();
};
el.ondragover = function (event) { // 清除默认事件,防止浏览器直接打开图片文件
event.stopPropagation();
event.preventDefault();
};
el.ondrop = function (event) {
event.stopPropagation();
event.preventDefault();
fn(event.dataTransfer.files[0]);
};
}
复制代码
更好的做法是在div里再放一个type='file'的input,然后绑定点击div事件触发input的点击事件,这样就可以同时支持点击及拖放上传
二、图片编辑
解决完文件上传之后,接着就需要对文件数据进行操作啦!首先我们拿图片文件来练手,这里我们分几个步骤:
1、图片预览实现
首先需要了解一个API:FileReader;
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。 ---来自MDN
直接上代码
function file2url(file, fn) {
const reader = new FileReader();
reader.addEventListener('load', function () {
const src = reader.result;
fn(src);
}, false);
reader.readAsDataURL(file);
}
复制代码
- 1、首先我们初始化一个 FileReader 的实例 reader ;
- 2、然后我们监听实例 reader 的 load 事件,将 reader.result 中包含的数据保存到变量 src
- 3、最后我们调用 reader.readAsDataURL() 方法处理目标文件 file ;
通过 FileReader.readAsDataURL() 方法,我们可以成功将图片文件转换成一串以 URL格式的字符串 (base64编码)表示所读取文件的内容(FileReader还可以将文件转换成文本格式,此处先不涉及),我们可以将转换后的url赋值给img元素的src属性,这样就可以查看图片预览了
fileInput.addEventListener('change', function () {
showFileName(this.files[0]);
file2url(this.files[0], function (src) {
document.querySelectorAll('img')[0].src = src;
})
});
复制代码
2、图片编辑
熟悉PS的肯定知道,在位图里整张图片由N多的像素点组成,每一个小的像素点可以想象成一个小的色块,N多色块拼接在一起就成了我们最终看到的图片,如果能操作每个像素点的色值,就能够对图片进行编辑了,我们开始吧:
首先还是一个几个API:(一个个介绍有点长,请自行点击链接去查看相关信息)
- 1、CanvasRenderingContext2D.drawImage():在canvas上绘制目标图片
- 2、CanvasRenderingContext2D.getImageData():获取canvas内容的数据
- 3、CanvasRenderingContext2D.putImageData():将已有的图片数据绘制到canvas
试着用这几个API将图片反色,主要代码如下:
// 将图片反色
function inverse(src) {
const img = new Image,
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
let w,h,data;
img.src = src;
const imgLoad = new Promise((resolve, reject) => {
img.onload = function () {
w = this.width;
h = this.height;
canvas.width = w;
canvas.height = h;
ctx.drawImage(this, 0, 0, w, h);
data = ctx.getImageData(0, 0, w, h);
const obj = {
data: data,
width: w,
height: h
};
resolve(obj);
};
});
// 改变图片像素
imgLoad.then((val) => {
return new Promise((resolve, reject) => {
let imgData = val.data.data;
let w = val.width;
let h = val.height;
for(let i = 0; i < h; i++) { // 遍历像素点
for(let j = 0; j < w; j++) {
let x = i * 4 * w + 4 * j;
imgData[x] = 255 - imgData[x];
imgData[x + 1] = 255 - imgData[x + 1];
imgData[x + 2] = 255 - imgData[x + 2];
}
}
ctx.putImageData(data, 0, 0);
resolve(canvas.toDataURL("image/jpeg", 1));
});
}).then(function (url) {
document.querySelector('.showNewImg').src = url;
});
}
复制代码
需要注意的地方:
- 文件的操作是异步进行的,此处用了Promise;
- 对像素点的处理用到了嵌套的循环,外层循环X轴,内层循环Y轴上与之交叉的像素点,每一个像素点由4个数据表示,分别对应RGBA;
因此R值的下标为:X轴序号 * 4 * 图片宽度 + Y轴序号 * 4
G值的下标为R值下标+1,B值的下标为R值下标+2,A值的下标为R值下标+3
编辑后的图片文件下载
下载的实现这里用到的是a标签的download属性;
主要代码如下:
function download(url, fileName) {
const link = document.createElement('a');
link.href = url;
link.download = fileName;
link.click();
}
复制代码
总结
- 图片的操作还能实现很多其他的效果,贴一个之前写的二维码图片合成页面,这个页面写的比较早,代码有点乱,不过本篇内容出自对该页面的梳理;
- 接下来还会继续整理,dom转换图片,.html文件编辑等其他文件相关操作;
- PS:本篇主要对图片的操作做了个简单的总结,代码的实现并没有考虑兼容等(最喜欢写demo这种无拘无束放飞自我的感觉),限于作者能力有限,相关代码仅作示范,如有不足,烦请告知,谢谢