js檔案操作總結一:圖片篇

吳予安發表於2018-11-06

本篇主要涉及到:

  • 檔案上傳
  • 圖片編輯
  • 圖片檔案下載

一、檔案上傳

檔案上傳目前瞭解的主要有三種方式:

  • 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的點選事件,這樣就可以同時支援點選及拖放上傳

這裡是一個demo


二、圖片編輯

解決完檔案上傳之後,接著就需要對檔案資料進行操作啦!首先我們拿圖片檔案來練手,這裡我們分幾個步驟:

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、然後我們監聽例項 readerload 事件,將 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:(一個個介紹有點長,請自行點選連結去檢視相關資訊)

試著用這幾個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這種無拘無束放飛自我的感覺),限於作者能力有限,相關程式碼僅作示範,如有不足,煩請告知,謝謝

相關文章