本篇主要涉及到:
- 檔案上傳
- 圖片編輯
- 圖片檔案下載
一、檔案上傳
檔案上傳目前瞭解的主要有三種方式:
- 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;
})
});
複製程式碼
稍微修改一下上一步的demo,讓它實現圖片預覽的功能,點選這裡檢視
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
將圖片反色的demo,點選這裡檢視。
編輯後的圖片檔案下載
下載的實現這裡用到的是a標籤的download屬性;
主要程式碼如下:
function download(url, fileName) {
const link = document.createElement('a');
link.href = url;
link.download = fileName;
link.click();
}
複製程式碼
增加下載功能的demo,點選這裡檢視。
總結
-
圖片的操作還能實現很多其他的效果,貼一個之前寫的二維碼圖片合成頁面,這個頁面寫的比較早,程式碼有點亂,不過本篇內容出自對該頁面的梳理;
-
接下來還會繼續整理,dom轉換圖片,.html檔案編輯等其他檔案相關操作;
-
PS:本篇主要對圖片的操作做了個簡單的總結,程式碼的實現並沒有考慮相容等(最喜歡寫demo這種無拘無束放飛自我的感覺),限於作者能力有限,相關程式碼僅作示範,如有不足,煩請告知,謝謝