1. 程式人生 > >簡單封裝一個上傳外掛——支援拖拽和預覽

簡單封裝一個上傳外掛——支援拖拽和預覽

最近碰到一個需求。需要上傳很多圖片,但是又不是批量上傳。場景是這樣的。我需要從資料表中查出一行一行的資料,每一行都需要更新一個對應的圖片。天才需求方不喜歡批量上傳,因為需要讓他們給每個圖片命名。
原生input flie上傳能滿足對方需求,但是不能方便拖拽和預覽圖片。
作為一個二手前端,當然是到網上找各種外掛。但是能在網上上架的外掛都封裝得太複雜,畢竟我使用的是很簡單的功能,用不上那麼牛逼的外掛。無奈之下自己動手寫了一個簡單的。

html排版

核心思路:把input設為透明,放在一個div中。
具體實現:最外層套一個固定寬高的div,同時把div設為相對定位。內層寫一個同樣寬高,透明的上傳input,設為絕對定位(這樣能保證與外層div完全重合)。內層同一級再寫一個div,用來存放文字,如“請將圖片拖到此處”。

<div class='box' style='position:relative;width: 100px;height: 50px;border:1px solid #000'>
        <input type="file" class='browerfile' name="copy_pic[]"  style='position:absolute;width:100px;height:50px;float:left;opacity:0;z-index: 3'  id="datafile" />
        <div class='box_txt' style='position:absolute;z-index:1;width: 100%;height: 50;text-align:center;line-height: 50px;color:gray'
>
圖片拖到此處</div> </div>

頁面開啟效果。
這裡寫圖片描述

其實這樣就能實現檔案的拖動上傳了,但是整個功能的需求還需要一個預覽的功能。

JS實現預覽圖片

其實,這裡並沒有直接把圖片展示到頁面,考慮到上傳頁面圖片太大,都展示出來印象頁面美觀。所以,這裡使用了一個bootstrap的彈出框popover,當點選的時候才彈出預覽框。
核心思路:通過js獲取頁面上的圖片地址,再將地址放到img標籤中。
具體實現:使用change繫結到圖片上傳框上,當檢測圖片拖動過來時,呼叫獲取圖片地址方法。將獲取到的圖片放到外層div下,與上傳input同級。(這裡使用一個a標籤,當點選的時候在彈出框中預覽圖片)。

 //獲取圖片路勁的方法,相容多種瀏覽器,通過createObjectURL實現
function getObjectURL(file){
    var url = null;
    if(window.createObjectURL != undefined){
        url = window.createObjectURL(file);//basic
    }else if(window.URL != undefined){
        url = window.URL.createObjectURL(file);
    }else if(window.webkitURL != undefined){
        url = window.webkitURL.createObjectURL(file);
    }
    return url;
}


//實現上傳樣式
$(function(){
    $(".browerfile").change(function(){
        $(this).prev('.showpic').remove();
        var objUrl = getObjectURL(this.files[0]);
        if(objUrl){
            $(this).parent('.box').prepend('<a style="position:absolute;z-index:999;text-align:center;color:red" class="showpic" href="javascript:">已選擇,預覽</a>');
            var elem = $(this).prev('.showpic');
            elem.popover({
                trigger: 'mouseover', //觸發方式
                placement:'bottom',
                html: true, // 為true的話,data-content裡就能放html程式碼了
                content: "<img src="+objUrl+" style='width:240px;height:320'/>", //這裡可以直接寫字串,也可以 是一個函式,該函式返回一個字串;
            });
        }
    })

})

好了,到此我們的圖片上傳外掛就完成了。簡單好用。
這裡寫圖片描述

但是在使用過程中發現一個問題。這裡我深刻的體會到了“墨菲定律”。“如果事情有變壞的可能,不管這種可能性有多小,它總會發生。”
為了避免圖片拖到上傳框外面,導致檔案被瀏覽器開啟。我儘可能的把上傳框調到很大,但是仍然會被反饋,檔案被瀏覽器打開了。
所以,這篇文章才出現第三天。或者說這篇文章才出現,如果不是為了解決這個問題,我也不會寫這篇文章。

優化功能

當然,為了使外掛變得好用。需要發現問題後積極去解決。
如何去解決這個問題呢,其實也很簡單。兩行程式碼。
核心思路:當檔案拖動到瀏覽器,並鬆開時。js能否攔截到,並阻止瀏覽器開啟檔案?
實現思路:下面兩行程式碼中,第一行時當瀏覽器中有檔案進入時,做出反應,不處理。第二行是當瀏覽器介面中,拖動檔案的滑鼠鬆手時,做出反應,這裡同樣,不處理。

document.ondragover=function(e){e.preventDefault();}
document.ondrop=function(e){e.preventDefault();}

當使用這兩行程式碼到外掛中時。很成功,圖片不會被開啟。但是也很失敗,上傳框中也不能接受拖動上傳了。

這裡我第一想法是,使用jquery類似的:not()選擇器。但是作為一個二手前端,沒有發現JavaScript有類似的功能(因為上面兩個方法,jquery不支援),或許真沒有。

找了半天后,我想到了一個辦法,不知道ondrop這個方法例項化的e物件,是否能檢測到當前操作的class或者id? 通過console.log列印之後還真發現能檢測到。所以,我的程式碼改成了下面部分。

document.ondragover=function(e){e.preventDefault();};
document.ondrop=function(e){
    // console.log(e);
    if (e.target.className=='browerfile') {
        return ;
    }else{
        alert('大哥,請拖動到上傳區域才能上傳。')
        e.preventDefault();
    }

}

這裡寫圖片描述

好了,終於成功完成任務。這個小外掛也離完美更近了一步。

其實為什麼寫這篇文章,主要還是因為拖動檔案、禁止瀏覽器開啟檔案、限制部分div不能拖動的相關文章還是比較少。畢竟h5都使用那麼廣了。