jQuery – JavaScript – 教你如何顯示上傳前的多筆預覽圖

* 如果您想要用套件可以來這篇 (2017/03/07更新)


前言可以快速帶過

上一篇 提到預覽圖的製作,使用了 Web APIs 的 FileReader 。後來經過網友的建議與提醒,以及我在實測後發現,一旦使用 FileReader 來讀取檔案,那麼系統資源上會比較吃重,因為瀏覽器會完整讀取你選擇的的每個檔案。所以如果一次選取數十個,瀏覽器就會停擺。網友建議如果只是製作預覽圖,可以改用 URL.createObjectURL() 這個方法。

目標

  1. 多檔預覽。如 Flickr 上傳圖片
  2. 結構化程式碼

解決方法

  1. 使用 vmodel.js 結構化
  2. 使用 URL.createObjectURL() 這個方法來完成

線上測試

 

HTML

CSS

jQuery/JavaScript

解說

一開始有一個參數,是用來後面做為不間斷的 <img><img><img> 存放。

接著我們透過 autoload() 可以告訴 vmodel 自動觸發要使用的方法,有 change_file() 這麼一個。

首先我們綁定使用者選取圖片的事件,點擊以後會呼叫 local_show(); 並把 input 傳入

當使用者有選取檔案後,才會觸發清空 local_clean() 、批次顯示 local_each_img()

清空,主要是把預覽的區域清空,避免不斷選取會不斷堆疊

因為這次的範例,使用者可以複選圖檔,所以我們使用 $.each 把每張圖片呼叫出來,並利用 URL.createObjectURL() 取得獨特的網址,讓該網址做為預覽圖的路徑。

其中使用了 local_create_imgcode() 主要是建立圖片編碼,但不直接透過 jQuery 的 append() 或 prepend() 寫入 HTML。這是因為多次插入 DOM 會影響校能,例如有50張圖片那瀏覽器資源不足可能會停擺,所以我們要做的是,在最後一次性的插入DOM。

最後 vs.imgcode 會成為一個不間段的標籤字串,我們才在最後加入 DOM,這樣效能才會好。最後我們還原選取鈕供下一次使用。

透過上面 vmodel 結構化 jQuery 與這次的範例目標,整個物件的感覺就更加強烈,維護上也方便許多。關於 vmodel.js 的寫法與文件,可以參考我的 github 或網站 內部相關文章

那麼如果不使用 vmodel 那要如何組織你的 jQuery 呢?我這邊就以 jQuery 建議與修改,做為組織程式碼的方法做為範例。

當然相較之下,會是使用 vmodel 的可塑性高出許多囉!

 


Comments

  1. 您好,

    讀完本文,有問題無法理解,
    問題如下:

    1)
    前端使用上預覽圖片沒有問題,但是….
    似乎因為第38行執行local_reset()後,要上傳的資料被清掉了
    如:http://www.chit.com.tw/zSelect.asp

    2)
    如果不執行local_reset(),註解掉以後
    若重新選擇圖片,圖片會一直堆疊無法清除
    按了reset鍵,input會清除,重選圖片後圖片依然會繼續增加

    找多圖片上傳前預覽的方法有好多天了
    您的方法是其中最喜愛的
    若您時間允許,是不可以協助指點呢?
    打擾您了~~

    萬分感謝~~

    • 最近很少更新這裡現在才發現好多人留言XD
      基本上這邊介紹的就是基礎應用。如果要搭配上傳,只要稍作變化就可以了,我自己連接後端上傳沒有問題喔~
      可以再思考一下如何改變。local_reset()是必要的喔,不使用會堆疊是正常的。
      謝謝你的認同,很感謝你~~~

      • 謝謝您
        我沒有想到解決辦法
        最後加了一個按鈕
        請User按那個按鈕將頁面reload重新選擇圖片^^
        自己該用心學習jQuery了
        再次感謝~~

        • 你是說顯示區域的圖片堆疊嗎?突然意會~
          如果是的話,使用 $(selector).html(”); 看看

  2. 不好意思,想請問”未選擇任何檔案”是否有方法可以移除?
    若您方便回答,再請您幫忙了,謝謝!:)

  3. 請問~如果我對每張圖做一個小叉叉,點了可以刪除單一圖片,這樣要怎麼寫比較好呢@@?
    我用jquery做click沒有效果…想請原po指點一下~感謝~

    • 這個算蠻基本的呢,基礎要再反覆練習一下。Google 搜尋 jquery 的 on() 相關教學試試

  4. 您好~看到原po的方法覺得很實用
    不過目前套用在本人專案上時卻發生想不通的問題
    我是使用您下面非vmodel的方法
    執行到 // 批次圖片,先清空後再插入 這段程式碼時就沒有執行成功了
    圖片的預覽也沒有出現 卡好久還是想不通
    想請教這會是什麼問題呢?感謝~

    • 嗯…這樣的話我也不是很懂,有相關的程式碼片段嗎?

      • 早安你好,以下為我的程式碼片段
        在JS的部分段落中我有加入alert()函數來判斷有沒有執行到
        不過卻只有在進入此頁面時跳出alert(‘change’)
        選取檔案後除了有顯示選擇的檔案名稱 圖片預覽並未出現
        會是我撰寫的部分有錯誤或是少了什麼嗎?
        (不好意思有點長,有空方便回答的話,再請您幫忙了,謝謝!)
        ————————————-
        //連續顯示上傳圖片
        var Preview = new function (){
        var root = $(“.text-center”);
        // 連續的圖片編碼
        var imgcode = ”;
        // 選取發生改變
        this.change_file = function (){
        root.on(“change”, “.userfile”, function (){
        show(this);
        alert(this);
        });
        alert(‘change’);
        }
        // 批次圖片,先清空後再插入
        var show = function (input){
        alert(‘show’);
        if (input.files && input.files[0]) {
        //clean();
        alert(‘show2’)
        each_img(input.files);
        }
        }
        // 批次讀取,最後再一次寫入
        var each_img = function (files){
        $.each(files, function (index, file){
        var src = URL.createObjectURL(file);
        alert(src);
        create_imgcode(src);
        });
        // 放置預覽元素後重設
        root.find(“.preview”).html(imgcode);
        alert(‘put’);
        //reset();
        }
        // 建立圖片
        var create_imgcode = function(src){
        imgcode += ”;
        alert(imgcode);
        }
        }
        // 執行
        Preview.change_file();
        ———————————————–

  5. 不好意思 請問這種方法可以再加以寫入PHP 的BLOB類型嗎

    • 你想要的是 PHP 透過 Blob 讀取伺服器資料夾的圖片嗎?我想網路有很多資源你先找找,等我有時間再寫。

發表迴響