changed 5 years ago
Linked with GitHub

JS HTML5拖拽上傳圖片預覽

tags : w3HexSchool . javascript

有時可以看到 , 將圖片拖曳至此上傳圖片的區塊 ( ex : HackMD 的編輯區塊 ) , 這個東西是如何實現的呢 ?

重要 API : File API . Drag API

Tree 查過之後 , 發現其中有 2 個重要的 Browser API 需要了解後才能製作

  • 檔案操作 : File API
​​const reader = new FileReader(); // 建立檔案讀取器 , 將上傳的圖片資料取出 ​​reader.onload = (e => img.src = e.target.result); // 註冊讀取完成後 , 執行的動作 ​​reader.readAsDataURL(file); // 取出 file 中的 base64 格式 data
  • 拖曳相關事件 : Drag API
    • dragenter : 拖曳圖片 進入 區塊時觸發
    • dragleave : 拖曳圖片 離開 區塊時觸發
    • dragover : 拖曳圖片於區塊中 移動 時觸發
    • drop : 於區塊中 放開 拖曳的圖片時觸發

上述 Drap API 預設動作皆為 轉址到檔案位置 ,
因此需要 防止預設事件 preventDefault 和 終止事件傳導 stopPropagation

實作開始

了解 API 的基礎原理後 , 讓我們開始製作一個 圖片拖曳的預覽區塊吧 !

製作步驟概要

  • 將預設的 dragenter . dragover . drop 行為取消掉
  • 實作 drop 行為 , 並處理上傳的 files 陣列
  • 將預計上傳的圖片顯示出來
  • 圖片向伺服器儲存

先設定骨架以及長相

建立一個 upload_zone

<div id="upload_zone" class="upload_zone"> 請將要上傳的圖片拖曳至此 </div>

將 upload_zone 上底色

.upload_zone { width: 200px; height: 200px; margin: 20px; padding: 10px; cursor: pointer; background-color: aqua; }

Drag 相關的 API

建立 dragenter . dragover . drop 的函數 , 以防止預設事件 & 終止事件傳導 ( 避免圖片拖曳造成的轉址問題 )

function dragenter(e) { e.stopPropagation(); //終止事件傳導 e.preventDefault(); //終止預設行為 } function dragover(e) { e.stopPropagation(); //終止事件傳導 e.preventDefault(); //終止預設行為 } function drop(e) { e.stopPropagation(); //終止事件傳導 e.preventDefault(); //終止預設行為 }

註冊 dragenter . dragover . drop 事件到 upload_zone

const dropbox = document.getElementById("upload_zone"); dropbox.addEventListener("dragenter", dragenter, false); dropbox.addEventListener("dragover", dragover, false); dropbox.addEventListener("drop", drop, false);

設定 dragenter 事件觸發後的樣式 A

.upload_zone_enter { border: 10px dashed black; background-clip: content-box; }

dragenter 時追加樣式 A , dragleave 時移除樣式 A 到 upload_zone

const dragleave = () => dropbox.classList.remove("upload_zone_enter"); function dragenter(e) { + dropbox.classList.add("upload_zone_enter"); e.stopPropagation(); //終止事件傳導 e.preventDefault(); //終止預設行為 } dropbox.addEventListener("dragleave", dragleave, false);

實作 Drop 行為並顯示拖曳的圖片

將 Drag 的圖片顯示到 preview 中

function handleFiles(files) { for (var i = 0; i < files.length; i++) { const file = files[i]; const imageType = /image.*/; if (!file.type.match(imageType)) { continue; } const img = document.createElement("img"); img.classList.add("preview_image"); img.file = file; preview.appendChild(img); // 將圖片加到 preview 上 const reader = new FileReader(); reader.onload = (e => img.src = e.target.result); reader.readAsDataURL(file); } } function drop(e) { e.stopPropagation(); e.preventDefault(); + const dt = e.dataTransfer; + const files = dt.files; // 取得被拖曳的圖片 + handleFiles(files); + dropbox.classList.remove("upload_zone_enter"); }

設定 preview 中的圖片樣式

.preview_image { width: 200px; height: 200px; }

完成上方設定後 , 將會得到下方圖片之效果

成品展示

參考資料

Select a repo