iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0


今天要來做的是滑鼠拖拉事件,點選笑臉圖片可以把它拖放到空的正方形中,


功能拆解

  • 預設情況圖片會放在第一個正方形內
  • 持續按著滑鼠左鍵,可以拖拉照片
  • 抓起圖片經過五個正方形時,正方形的background-color會變成灰色,border為虛線
  • 放開滑鼠左鍵,圖片就會放在正方形內

事前準備

  1. 一張喜歡的圖片

運用知識點羅列

  • HTML
知識點 使用說明
HTML Global Attributes 加入dragable屬性,使元素可被拖動
  • CSS
知識點 使用說明
@media query 在此設定較小視窗要直向排列
background 縮寫屬性,設置背景圖片、位置等
  • JS
知識點 使用說明
dragEvent 定義托放的事件物件
querySelectorAll 回傳nodeList,獲取HTML元素
querySelector 返回第一個符合特定選擇器的元素
for of 在此迭代未被填滿的正方形
this 在一般function和箭頭函式內使用
setTimeout 某段時間後執行某個函式(一次)

流程講解

  • HTML
    設五個<div>,其中一個加上一些預設的class="fill hold",draggable屬性設為true
    fill:圖片預設填滿一個正方形
    hold:持續按壓滑鼠左鍵的狀態
    <div class="square">
        <div class="fill" draggable="true"></div>
    </div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
  • CSS
    大局配置
* {
  box-sizing: border-box;
}

body {
  background-color: steelblue;
  margin: 0;
  padding: 0;
  display: flex; /*讓內容水平垂直置中*/
  justify-content: center;
  align-items: center;
  height: 100vh;
  overflow: hidden;
}

正方形相關

.square {
  background-color: white;
  height: 150px;
  width: 150px;
  margin: 10px;
  border: 3px solid black;
}
/* 圖片填滿狀態 */
為了讓圖片不要蓋住邊框,所以寬和高稍微設小一點
.fill {
  background: url("...")  no-repeat center/ cover black ; /*一般會在最後加入背景色,以防圖片沒顯示*/
  cursor: pointer;
  width: 145px;
  height: 145px;
}
/* 滑鼠按壓不放時的狀態 */
.hold {
  border: 3px dashed black;
}
/* 圖片經過正方形時,正方形的狀態 */
.hover {
  background-color: gray;
  border: 3px dashed white;
}

HTML、CSS設定好,呈現如下圖,圖片加減看XD 因沒辦法截到滑鼠游標,圖片因為draggable設為true的關係,讓滑鼠游標可拖曳,你可以試試看false和auto(預設,根據瀏覽器的默認行為)會有甚麼效果
https://ithelp.ithome.com.tw/upload/images/20220924/20149362dLYy76dotc.png

  • JS
    首先我們要先認識拖拉事件的事件類型有哪些

Drag And Drop Events

  1. dragstart 開始拖動元素或文本選擇時會觸發此事件
  2. dragend 拖動操作結束(釋放鼠標按鈕或按下退出鍵)時會觸發此事件
  3. dragover 滑鼠拖動元素或文本選擇並經過有效的放置目標上時,會連續觸發此事件
  4. dragenter 拖動的元素或文本選擇進入有效的放置目標時會觸發此事件。
  5. dragleave 拖動的元素或文本選擇離開有效的放置目標時會觸發此事件。
  6. drop 當元素被放置在有效放置目標上時會觸發此事件。

注意注意!!以上事件都沒有使用camel case,都是小寫
認識了拖拉事件的類型,為這個賽project畫了一個流程圖,如下:
https://ithelp.ithome.com.tw/upload/images/20220924/20149362vEdCFTDMdq.png

定義拖拉function
整個行為是我們會在特定的時間觸發拖拉事件,所以先把有關的拖拉事件function寫好,console.log印出來是為了幫助我們理解事件觸發的順序和時間點

// 開始
function dragStart() {
  console.log("drag start");
}
// 拖動一個元素
function dragOver() {
  console.log("drag over");
}

// 拖動進入某個東西裡
function dragEnter() {
  console.log("drag enter");
}
// 拖動離開某個東西
function dragLeave() {
  console.log("drag leave");
}

// 放下
function dragDrop() {
  console.log("drag drop");
}
// 結束
function dragEnd() {
  console.log("drag end");
}

接著,我們看底下這張圖,根據行為區分,我們可以把元素大致上區分為填滿和未填滿
https://ithelp.ithome.com.tw/upload/images/20220924/20149362x6U6f5TxMG.png

變數宣告

let fill = document.querySelector(".fill");  //填滿
let square = document.querySelectorAll(".square");  //未填滿

事件監聽

//填滿
fill.addEventListener("dragstart", dragStart);
fill.addEventListener("dragend", dragEnd);

//未填滿
for (let element of squares) {
  console.log(element); //squares變數裡的每個元素
  element.addEventListener("dragover", dragOver);
  element.addEventListener("dragenter", dragEnter);
  element.addEventListener("dragleave", dragLeave);
  element.addEventListener("drop", dragDrop);
}

了解了事件的觸發點後,我們回到一開始定義拖拉function的地方,稍作修改

// 開始
function dragStart() {
  console.log("drag start");
  this.className += " hold";
  setTimeout(() => (this.className = "invisible"), 0);
}

// 拖動一個元素
function dragOver(e) {
  console.log("drag over");
  e.preventDefault();
}

// 拖動進入某個東西裡
function dragEnter(e) {
  console.log("drag enter");
  e.preventDefault();
  this.className += " hover";
}

// 拖動離開某個東西
function dragLeave() {
  console.log("drag leave");
  this.className = "square";
}

// 放下
function dragDrop() {
  console.log("drag drop");
  this.className = "square";
  this.append(fill);
}

// 結束
function dragEnd() {
  console.log("drag end");
  this.className = "fill";
}

附上codepen連結 https://codepen.io/hangineer/pen/VwxMNom


補充

  1. 其他的HTML Global Attributes
  2. Media Query (媒體查詢)
  3. 淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
    4.append和appendChild的差別

若有解說不夠詳盡或是錯誤歡迎指教,感激不盡!/images/emoticon/emoticon41.gif


參考資料

50 Projects In 50 Days - HTML, CSS & JavaScript
HTML Drag and Drop API
DragEvent


上一篇
Day 17 Side Project : Theme Clock 動態時鐘(下)
下一篇
Day 19 Side Project : Double Vertical Slider雙捲軸
系列文
在30天利用HTML & CSS & JavaScript完成Side Project實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言