前端圖片預覽功能實現

不少時候咱們都會有圖片上傳的功能需求,若是咱們先將圖片上傳到服務器,而後在將返回結果顯示在前端,這樣的操做性能開銷太大,若是圖片一多,簡直要哭,並且萬一還碰到了上傳錯誤要刪除的,那簡直沒法想象了。因此咱們須要先將圖片在前端展現後,而後由用戶確認沒有問題了,再統一上傳,這樣纔是比較理想的。css

input

type=file

相信你們都知道,要在前端實現圖片的上傳,咱們離不開的是一個 <input> type=file 的 input 元素,該元素能夠容許用戶選擇一個或者多個文件。html

<input type="file">
複製代碼

此時,咱們點擊 input 元素,就能夠瀏覽本地文件並選擇上傳。可是,此時咱們只能選擇一個文件,而不能多個。這時就須要 <input> 標籤的另外一個屬性 multiple前端

multiple

multipla 屬性容許用戶選擇多個文件,他是一個不須要值的屬性,也就是說,只要你的 input 標籤上出現了這個屬性,那麼不論其值是什麼,他都會支持多文件選擇。一般來講咱們使用 multiple 只會使用其屬性名,而不會給他加值web

<input type='file' multiple>
複製代碼

accept

若是你嘗試了以上標籤及屬性,你會發現你的不但能選擇 image 文件,還能選擇其餘各類各樣的文件。可是通常來講對咱們有須要的只是 image 文件,至於其餘什麼的,愛咋咋地吧,只要不出來妨礙我就能夠了。因此這時候咱們須要 accept 的屬性來進行限制。accept 屬性接受逗號分隔的 MIME 類型字符串:數組

1. accept='image/png' 或者 accept='.png' --只接受 .png 格式的圖片
2. accept='iamge/png,image/jpeg' 或者 accept='.png, .jpg .jpeg' 接受 .png .jpeg .jpg 格式的圖片
3. accept='image/*' 接受全部類型的 image 


    <input type='file' multiple accetp='image/*'>
複製代碼

注: 'image/*' 在部分瀏覽器中(Chrome和Safari等Webkit瀏覽器)響應比較緩慢,能夠用如下方法代替瀏覽器

<<input type="file" multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif'> 
複製代碼

樣式

通常來講咱們都會將 input 設置爲 display:none, 而後經過 label 來設置其顯示樣式服務器

// css

    input{
        display:none;
    }
    label{
        // 關於label樣式
    }

    // html

    <input type='file' multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif' id='inputFile'>
    <label for="inputFile">上傳圖片</label>
複製代碼

FileList 對象

選中文件經過 HTMLInputElement.files 屬性返回了一個 FileList 對象,這個對象是一個包含了許多 file 文件的列表。每一個 file 對象包含了一下信息:app

1. name:文件名
2. lastModified:文件最後一次修改時間(時間戳形式)
3. lastModifiedDate:文件最後一次修改時間(UNIX timestamp形式)
4. size: 文件大小(byte 爲單位)
5. type:文件 MIME 類型
複製代碼

咱們能夠經過對 input 標籤監聽 change 事件:異步

//  js

    document.getElementById('inputFile').addEventListener('change', changeHandler, false);

    function changeHandler(e) {
        var files = e.target.files;
        console.log(files) // 這裏咱們能獲取到所選擇的文件信息,須要注意的一點是 files 是個類數組對象。
    } 
複製代碼

FileReader or 對象 URL

當咱們獲取到文件對象信息 files 了之後,咱們要如何將他在頁面上預覽出來,這裏提供了兩種方法:FileReader 或者 對象 URL。
這兩種方法該如何使用,又有何區別呢?svg

1. FileReader

FileReader 實現了一種異步的讀取機制。他必須先經過 FileReader() 構造函數建立出一個 fileReader 實例。該實例實現了一下幾個方法和事件(部分):

  1. readerAsDataURL(file): 讀取文件並以數據 URI 形式保存在 result 屬性中

  2. load 事件:在文件加載成功後觸發 load 事件

  3. error 事件:在文件加載失敗後觸發 error 事件

  4. progress 事件:在讀取文件的過程當中觸發 progress 事件,該事件能夠近似(間隔性觸發,不是實時響應)監聽文件上傳進度。該方法有三個屬性:lengthComputable(進度信息是否可用), loaded(已經加載了多少), total總共有多少。

usage:

files.forEach(function(item) {
        var reader = new FileReader();
        reader.readAsDataURL(item);
        reader.onprogress = function(e) {
            if (e.lengthComputable) {
                // 簡單把進度信息打印到控制檯吧
                console.log(e.loaded / e.total + '%') 
            }
        }
        reader.onload = function(e) {
            var image = new Image()
            image.src = e.target.result
            body.appendChild(image)
        }
        reader.onerror = function(e) {
            console.log('there is an error!')
        }
    })
複製代碼

2. 對象 URL

對象 URL 指的是引用保存在 File 或 Blob 中的數據 URL。使用對象 URL 的時候不用像 FIleReader 同樣要先把數據讀取到 JavaScript 中,他能夠引用 內存中 URL 地址而使用。

建立對象 URL 方法: window.URL.createObjectURL()。兼容寫法:

function creatObjectURL(file) {
        if (window.URL) {
            return window.URL.createObjectURL(file);
        } else if (window.webkitURL) {
            return window.webkitURL.createObjectURL(file);
        } else {
            return null
        }
    }
複製代碼

usage:

files.forEach(function(item) {
        var url = createObjectURL(item)
        var image = new Image()
        image.src = url
        body.appendChild(image)
    })
複製代碼

區別:

參(zhao)考(chao)

  1. FileReader 是異步操做,而對象 URL 是同步操做

  2. FileReader.readAsDataURL 返回的是一個包含更多字節的 base64 格式,createObejctURL 返回的是一個帶 hash 的 URL。

  3. 因爲二者返回形式不一樣,FileReader.readerAsDataURL 會佔用更多內存,可是當你再也不使用他的時候,他會自動釋放內存,而 createObjectURL 則只有當你的頁面關閉或者手動調用 revokeObejctURL 的時候才能釋放內存。

  4. 從兼容性來講: createObjectURL 和 FileReader.readerAsDataURL 都兼容 IE10+ 和現代全部主流瀏覽器

  5. createObjectURL 相對 FileReader.readerAsDataURL,效率較高。可是若是圖片較多,則最好手動清除內存,能夠把 URL 當作參數直接傳給 window.URL.revokeObjectURL()。兼容寫法:

    function revokeObjectURL(url) {
         if (widnow.URL) {
             return window.URL.revokeObjectURL(url)
         } else {
             return window.webkitURL.revokeObjectURL(url)
         }
     }
    複製代碼

簡單實現:

// css

    input{
        display:none;
    }
    label{
        // 關於label樣式
    }

    // html

    <input type='file' multiple accept='image/png, image/jpeg, image/jpg, image/svg, image/gif' id='inputFile'>
    <label for="inputFile">上傳圖片</label>

    // js 

    var inputFile = document.getElementById('inputFile')
    var body = document.body || document.getElementsByTagName('body')[0]

    inputFile.addEventListener('change', changeHandler, false)

    function changeHandler(e) {
        var files = Array.from(e.target.files)
        files.forEach(function(item) {
            var image = new Image()
            image.src = createObjectURL(item)
            body.appendChild(image)
            image.onload = function() {
                revokeObjectURL(this.src)
            }
        })
    }

    function createObjectURL(file) {
        if (window.URL) {
            return window.URL.createObjectURL(file)
        } else {
            return window.webkitURL.createObjectURL(file)
        }
    }

    function revokeObjectURL(file) {
        if (window.URL) {
            return window.URL.revokeObjectURL(file)
        } else {
            return window.webkitURL.revokeObjectURL(file)
        }
    }

     

        } else {
            前端學習培訓、視頻教程、學習路線,添加威信  kaixin666haoyun  與我聯繫
        }
做者:愛創課堂前端技術分享 連接: 來源:掘金 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索