# 動態圖片之新增、刪除與排序 ### **撰寫程式:HTML | CSS | JS** * [codepen](https://codepen.io/liu_0821/pen/WNaYrEq) * [Medium](https://medium.com/@LindaLiu0821/%E5%9C%96%E7%89%87%E5%8B%95%E6%85%8B%E6%96%B0%E5%A2%9E-%E5%88%AA%E9%99%A4%E8%88%87%E6%8E%92%E5%BA%8F-b41a053e760e) ![](https://hackmd.io/_uploads/S1hclhOH2.png) ## HTML 1. ##### HTML中的標籤`label`中的`for`,對應`input`的`Id`屬性。 ``` <div class = "main" id = "inBox"> <label for="addImage" class = "addImage" ></label> <input type="file" id="addImage" accept="image/*"> <div class="Box"> <div class="ImgBox"> <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQvi6Ul_hZD5W9dIpr8NQF13T7uybwNHtBwyw&usqp=CAU" alt=""> </div> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-circle-fill" viewBox="0 0 16 16"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM4.5 7.5a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1h-7z"/> </svg> </div> </div> ``` ## CSS 擷取片段 > ###### 大致上比較著需要注意的是`position`的使用,與`object-fit`圖片的區塊填滿設定。 ``` // 顯示圖片樣式 .Box{ position: relative; height: 150px; border: 1px solid #eeeeee; margin: .2rem .5rem; } .ImgBox{ width: 150px; height: 100%; overflow: hidden; position: relative; // 滑鼠光標樣式 cursor: move; } .ImgBox > img{ position: absolute; top:50%; left:50%; display:block; max-width: 150px; max-height: 100%; transform:translate(-50%,-50%); object-fit: contain; } // 新增圖片樣式 .addImage{ cursor: pointer; width: 150px; height: calc(100% / 3.3); background-color: #eeeeee; display: flex; align-items: center; justify-content: center; margin: .2rem .5rem; font-family:'Noto Sans TC'; font-weight:700; } .addImage::before{ font-family:fantasy; content:"➕"; font-weight:900; } input[type='file']{ display:none; // 使用者點擊label,所以這個隱藏起來就好~ } ``` > ###### 動畫效果 ``` .animationShake{ animation: shake 800ms ease-in-out; animation-iteration-count:infinite; background-color: #eeeeee; } @keyframes shake { 10%,90%{ transform: translate3d(-1px,0,0); } 20%,80%{ transform: translate3d(2px,0,0); } 30%,70%{ transform: translate3d(-4px,0,0); } 40%,60%{ transform: translate3d(4px,0,0); } 50%{ transform: translate3d(-4px,0,0); } } ``` ## JS > ###### 點選要上傳的圖片 ``` $("label[for='addImage']").on('click', function (e) { // 使用one就只會執行一次 $('#addImage').one('change', function () { let fr = new FileReader();//建立FileReader物件 let file = this.files[0];//將上傳檔案轉換為base64字串 fr.readAsDataURL(file);// 使用 readAsDataURL 將圖片轉成 Base64 fr.onload = function (e) { runImg(e.target.result); }; }); }); ``` > ###### 新增`img`的標籤 ``` function runImg(data) { $('.main').append( ` <div class="Box"> <div class="ImgBox"> <img src="`+data+`" alt=""> </div> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-circle-fill" viewBox="0 0 16 16"> <path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM4.5 7.5a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1h-7z"/> </svg> </div> ` ); } ``` > ###### 移除`img`的標籤 ``` function removeBtn() { $(".bi.bi-dash-circle-fill").on('click', function (e) { let dom = $(e.target).parent().parent(); if($(dom).attr("class")==="Box"){ $(dom).remove(); } }); } ``` > ###### 排序( 圖與圖之間交換 ) ``` function moveImage(){ let ImgBox = $(".Box"); let inBox = document.getElementById("inBox"); console.log(ImgBox) let container=null; // 給每個div去綁定事件 for(let i=0;i<ImgBox.length;i++){ // ondragstart 拖動執行 ImgBox[i].ondragstart=function(){ container=this; } // ondragover 拖動到目標放置 // ---> 在拖動時仍然保持抖動的動畫效果 ImgBox[i].ondragover=function(){ event.preventDefault(); $(this).addClass('animationShake'); } // ondragenter 拖動進入範圍時觸發 // ---> 保持只有被選取到的有效果 ImgBox[i].ondragenter = function(){ remove(); }; // ondrop 可拖動元素放置在div時執行 // ---> 確定好位置後清除動畫效果 ImgBox[i].ondrop=function(){ if(container!=null&&container!=this){ console.log(this) let temp=document.createElement("div"); inBox.replaceChild(temp,this); //用新建的div佔據目的位置 inBox.replaceChild(this,container);// 目的div放置在起始位置 inBox.replaceChild(container,temp) // 起始div放置在目的位置 } remove() } } } ``` > ###### 清除動畫效果 ``` function remove(){ let ImgBox =$(".Box"); $.each(ImgBox,function(ins,items){ $(items).removeClass('animationShake'); }); } ``` ### 如何避免圖片重複累加? 1. `$('#addImage')`的函式中使用`one`可確保只執行一次,避免重複讀取值。 2. 在`change`中`readAsDataURL`之下加上`$('#addImage').replaceWith('<input type="file" accept="image/*">')`,更新`input`的標籤,確保每次點選都是新的值也不會重複。 3. 在`change`之前,新增`$('#addImage').off('change');`事件移除再讓他重新註冊就可以喽。 --- ##### ヽ(∀゚ )人(゚∀)人( ゚∀)人(∀゚ )人(゚∀)人( ゚∀)ノヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人( ゚∀)人 ##### 以上 如果註解哪裡有錯誤或有問題,歡迎提出來一起討論~~~~