You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/th/3-terrarium/3-intro-to-DOM-and-closures
softchris a7d39944e9
🌐 Update translations via Co-op Translator
1 month ago
..
README.md 🌐 Update translations via Co-op Translator 1 month ago
assignment.md 🌐 Update translations via Co-op Translator 1 month ago

README.md

โครงการ Terrarium ตอนที่ 3: การจัดการ DOM และ JavaScript Closures

DOM และ closure

ภาพวาดโดย Tomomi Imura

ยินดีต้อนรับสู่หนึ่งในแง่มุมที่น่าสนใจที่สุดของการพัฒนาเว็บ - การทำให้สิ่งต่าง ๆ มีความโต้ตอบ! Document Object Model (DOM) เป็นเหมือนสะพานเชื่อมระหว่าง HTML และ JavaScript ของคุณ และวันนี้เราจะใช้มันเพื่อทำให้ terrarium ของคุณมีชีวิตชีวา เมื่อ Tim Berners-Lee สร้างเว็บเบราว์เซอร์ตัวแรก เขาได้จินตนาการถึงเว็บที่เอกสารสามารถเป็นแบบไดนามิกและโต้ตอบได้ - DOM ทำให้วิสัยทัศน์นั้นเป็นไปได้

เราจะสำรวจ JavaScript closures ซึ่งอาจฟังดูน่ากลัวในตอนแรก ลองนึกถึง closures ว่าเป็นการสร้าง "กระเป๋าความจำ" ที่ฟังก์ชันของคุณสามารถจดจำข้อมูลสำคัญได้ มันเหมือนกับแต่ละต้นไม้ใน terrarium ของคุณมีบันทึกข้อมูลของตัวเองเพื่อติดตามตำแหน่งของมัน เมื่อจบบทเรียนนี้ คุณจะเข้าใจว่ามันเป็นธรรมชาติและมีประโยชน์อย่างไร

นี่คือสิ่งที่เรากำลังสร้าง: terrarium ที่ผู้ใช้สามารถลากและวางต้นไม้ได้ทุกที่ที่ต้องการ คุณจะได้เรียนรู้เทคนิคการจัดการ DOM ที่ช่วยให้ทุกอย่างตั้งแต่การอัปโหลดไฟล์แบบลากและวางไปจนถึงเกมแบบโต้ตอบ มาทำให้ terrarium ของคุณมีชีวิตกันเถอะ

แบบทดสอบก่อนเรียน

แบบทดสอบก่อนเรียน

ทำความเข้าใจ DOM: ประตูสู่หน้าเว็บแบบโต้ตอบ

Document Object Model (DOM) คือวิธีที่ JavaScript สื่อสารกับองค์ประกอบ HTML ของคุณ เมื่อเบราว์เซอร์ของคุณโหลดหน้า HTML มันจะสร้างการแสดงผลแบบโครงสร้างของหน้านั้นในหน่วยความจำ - นั่นคือ DOM ลองนึกถึงมันว่าเป็นแผนผังครอบครัวที่ทุกองค์ประกอบ HTML เป็นสมาชิกครอบครัวที่ JavaScript สามารถเข้าถึง ปรับเปลี่ยน หรือจัดเรียงใหม่ได้

การจัดการ DOM เปลี่ยนหน้าคงที่ให้เป็นเว็บไซต์แบบโต้ตอบ ทุกครั้งที่คุณเห็นปุ่มเปลี่ยนสีเมื่อเลื่อนเมาส์ เนื้อหาที่อัปเดตโดยไม่ต้องรีเฟรชหน้า หรือองค์ประกอบที่คุณสามารถลากไปรอบ ๆ ได้ นั่นคือการจัดการ DOM ที่ทำงานอยู่

การแสดงผลแผนผัง DOM

การแสดงผล DOM และ HTML markup ที่อ้างอิงถึงมัน จาก Olfa Nasraoui

สิ่งที่ทำให้ DOM ทรงพลัง:

  • ให้ วิธีการที่มีโครงสร้างในการเข้าถึงองค์ประกอบใด ๆ บนหน้าเว็บของคุณ
  • ช่วยให้ อัปเดตเนื้อหาแบบไดนามิกโดยไม่ต้องรีเฟรชหน้า
  • อนุญาต การตอบสนองแบบเรียลไทม์ต่อการโต้ตอบของผู้ใช้ เช่น การคลิกและการลาก
  • สร้าง พื้นฐานสำหรับแอปพลิเคชันเว็บแบบโต้ตอบสมัยใหม่

JavaScript Closures: สร้างโค้ดที่มีการจัดระเบียบและทรงพลัง

JavaScript closure เปรียบเสมือนการให้ฟังก์ชันมีพื้นที่ทำงานส่วนตัวพร้อมหน่วยความจำที่คงอยู่ ลองนึกถึงนกฟินช์ของดาร์วินบนหมู่เกาะกาลาปาโกสที่แต่ละตัวพัฒนาปากที่เชี่ยวชาญตามสภาพแวดล้อมเฉพาะของมัน - closures ทำงานในลักษณะเดียวกัน สร้างฟังก์ชันเฉพาะที่ "จดจำ" บริบทเฉพาะของมันแม้ว่าฟังก์ชันแม่จะเสร็จสิ้นแล้วก็ตาม

ใน terrarium ของเรา closures ช่วยให้แต่ละต้นไม้จดจำตำแหน่งของตัวเองได้อย่างอิสระ รูปแบบนี้ปรากฏอยู่ทั่วการพัฒนา JavaScript ระดับมืออาชีพ ทำให้เป็นแนวคิดที่มีคุณค่าในการทำความเข้าใจ

💡 ทำความเข้าใจ Closures: Closures เป็นหัวข้อสำคัญใน JavaScript และนักพัฒนาหลายคนใช้มันมาหลายปีก่อนที่จะเข้าใจทุกแง่มุมทางทฤษฎี วันนี้เรามุ่งเน้นที่การใช้งานจริง - คุณจะเห็น closures เกิดขึ้นตามธรรมชาติเมื่อเราสร้างคุณสมบัติแบบโต้ตอบ ความเข้าใจจะพัฒนาขึ้นเมื่อคุณเห็นว่ามันแก้ปัญหาจริงได้อย่างไร

การแสดงผลแผนผัง DOM

การแสดงผล DOM และ HTML markup ที่อ้างอิงถึงมัน จาก Olfa Nasraoui

ในบทเรียนนี้ เราจะทำโครงการ terrarium แบบโต้ตอบของเราให้เสร็จสมบูรณ์โดยการสร้าง JavaScript ที่จะช่วยให้ผู้ใช้สามารถจัดการต้นไม้บนหน้าเว็บได้

ก่อนเริ่มต้น: การเตรียมตัวให้พร้อม

คุณจะต้องใช้ไฟล์ HTML และ CSS จากบทเรียน terrarium ก่อนหน้านี้ - เรากำลังจะทำให้การออกแบบแบบคงที่นั้นมีความโต้ตอบ หากคุณเพิ่งเข้าร่วมครั้งแรก การทำบทเรียนเหล่านั้นให้เสร็จก่อนจะช่วยให้คุณเข้าใจบริบทที่สำคัญ

นี่คือสิ่งที่เราจะสร้าง:

  • การลากและวางที่ราบรื่น สำหรับต้นไม้ใน terrarium ทั้งหมด
  • การติดตามพิกัด เพื่อให้ต้นไม้จดจำตำแหน่งของมัน
  • อินเทอร์เฟซแบบโต้ตอบที่สมบูรณ์ โดยใช้ JavaScript แบบ vanilla
  • โค้ดที่สะอาดและมีการจัดระเบียบ โดยใช้รูปแบบ closure

การตั้งค่าไฟล์ JavaScript ของคุณ

มาสร้างไฟล์ JavaScript ที่จะทำให้ terrarium ของคุณมีความโต้ตอบกันเถอะ

ขั้นตอนที่ 1: สร้างไฟล์ script ของคุณ

ในโฟลเดอร์ terrarium ของคุณ สร้างไฟล์ใหม่ชื่อ script.js

ขั้นตอนที่ 2: เชื่อมโยง JavaScript กับ HTML ของคุณ

เพิ่มแท็ก script นี้ในส่วน <head> ของไฟล์ index.html ของคุณ:

<script src="./script.js" defer></script>

ทำไมแอตทริบิวต์ defer ถึงสำคัญ:

  • รับรอง ว่า JavaScript ของคุณรอจนกว่า HTML ทั้งหมดจะโหลดเสร็จ
  • ป้องกัน ข้อผิดพลาดที่ JavaScript พยายามค้นหาองค์ประกอบที่ยังไม่พร้อม
  • รับประกัน ว่าองค์ประกอบต้นไม้ทั้งหมดของคุณพร้อมสำหรับการโต้ตอบ
  • ให้ ประสิทธิภาพที่ดีกว่าการวาง script ไว้ที่ด้านล่างของหน้า

⚠️ หมายเหตุสำคัญ: แอตทริบิวต์ defer ป้องกันปัญหาเรื่องเวลาโดยทั่วไป หากไม่มีมัน JavaScript อาจพยายามเข้าถึงองค์ประกอบ HTML ก่อนที่มันจะโหลดเสร็จ ซึ่งจะทำให้เกิดข้อผิดพลาด


การเชื่อมโยง JavaScript กับองค์ประกอบ HTML ของคุณ

ก่อนที่เราจะทำให้องค์ประกอบสามารถลากได้ JavaScript จำเป็นต้องค้นหาองค์ประกอบเหล่านั้นใน DOM ลองนึกถึงสิ่งนี้เหมือนระบบการจัดหมวดหมู่ในห้องสมุด - เมื่อคุณมีหมายเลขหมวดหมู่ คุณสามารถค้นหาหนังสือที่คุณต้องการและเข้าถึงเนื้อหาทั้งหมดของมันได้

เราจะใช้เมธอด document.getElementById() เพื่อทำการเชื่อมโยงเหล่านี้ มันเหมือนกับการมีระบบการจัดเก็บที่แม่นยำ - คุณให้ ID และมันจะค้นหาองค์ประกอบที่คุณต้องการใน HTML ของคุณ

การเปิดใช้งานฟังก์ชันการลากสำหรับต้นไม้ทั้งหมด

เพิ่มโค้ดนี้ในไฟล์ script.js ของคุณ:

// Enable drag functionality for all 14 plants
dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
dragElement(document.getElementById('plant4'));
dragElement(document.getElementById('plant5'));
dragElement(document.getElementById('plant6'));
dragElement(document.getElementById('plant7'));
dragElement(document.getElementById('plant8'));
dragElement(document.getElementById('plant9'));
dragElement(document.getElementById('plant10'));
dragElement(document.getElementById('plant11'));
dragElement(document.getElementById('plant12'));
dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));

นี่คือสิ่งที่โค้ดนี้ทำ:

  • ค้นหา องค์ประกอบต้นไม้แต่ละตัวใน DOM โดยใช้ ID เฉพาะของมัน
  • ดึง การอ้างอิง JavaScript ไปยังองค์ประกอบ HTML แต่ละตัว
  • ส่งต่อ องค์ประกอบแต่ละตัวไปยังฟังก์ชัน dragElement (ซึ่งเราจะสร้างต่อไป)
  • เตรียม ต้นไม้ทุกต้นสำหรับการโต้ตอบแบบลากและวาง
  • เชื่อมโยง โครงสร้าง HTML ของคุณกับฟังก์ชัน JavaScript

🎯 ทำไมต้องใช้ IDs แทน Classes? IDs ให้ตัวระบุเฉพาะสำหรับองค์ประกอบเฉพาะ ในขณะที่ CSS classes ถูกออกแบบมาเพื่อการจัดสไตล์กลุ่มขององค์ประกอบ เมื่อ JavaScript ต้องการจัดการองค์ประกอบแต่ละตัว IDs ให้ความแม่นยำและประสิทธิภาพที่เราต้องการ

💡 เคล็ดลับ: สังเกตว่าเรากำลังเรียก dragElement() สำหรับต้นไม้แต่ละต้นแยกกัน วิธีนี้ช่วยให้ต้นไม้แต่ละต้นมีพฤติกรรมการลากที่เป็นอิสระ ซึ่งจำเป็นสำหรับการโต้ตอบของผู้ใช้ที่ราบรื่น


การสร้าง Drag Element Closure

ตอนนี้เราจะสร้างหัวใจของฟังก์ชันการลากของเรา: closure ที่จัดการพฤติกรรมการลากสำหรับต้นไม้แต่ละต้น Closure นี้จะมีฟังก์ชันภายในหลายตัวที่ทำงานร่วมกันเพื่อติดตามการเคลื่อนไหวของเมาส์และอัปเดตตำแหน่งขององค์ประกอบ

Closures เหมาะสำหรับงานนี้เพราะช่วยให้เราสร้างตัวแปร "ส่วนตัว" ที่คงอยู่ระหว่างการเรียกฟังก์ชัน ทำให้ต้นไม้แต่ละต้นมีระบบการติดตามพิกัดที่เป็นอิสระ

ทำความเข้าใจ Closures ด้วยตัวอย่างง่าย ๆ

ให้ฉันแสดงตัวอย่างง่าย ๆ ที่แสดงแนวคิดของ closures:

function createCounter() {
    let count = 0; // This is like a private variable
    
    function increment() {
        count++; // The inner function remembers the outer variable
        return count;
    }
    
    return increment; // We're giving back the inner function
}

const myCounter = createCounter();
console.log(myCounter()); // 1
console.log(myCounter()); // 2

นี่คือสิ่งที่เกิดขึ้นในรูปแบบ closure นี้:

  • สร้าง ตัวแปร count ส่วนตัวที่มีอยู่เฉพาะใน closure นี้
  • ฟังก์ชันภายใน สามารถเข้าถึงและแก้ไขตัวแปรภายนอกนั้น (กลไกของ closure)
  • เมื่อเราส่งคืน ฟังก์ชันภายใน มันยังคงเชื่อมต่อกับข้อมูลส่วนตัวนั้น
  • แม้หลังจาก createCounter() เสร็จสิ้นการทำงาน count ยังคงอยู่และจดจำค่าของมัน

ทำไม Closures ถึงเหมาะสำหรับฟังก์ชันการลาก

สำหรับ terrarium ของเรา ต้นไม้แต่ละต้นจำเป็นต้องจดจำพิกัดตำแหน่งปัจจุบันของมัน Closures ให้โซลูชันที่สมบูรณ์แบบ:

ประโยชน์สำคัญสำหรับโครงการของเรา:

  • รักษา ตัวแปรตำแหน่งส่วนตัวสำหรับต้นไม้แต่ละต้นอย่างอิสระ
  • คงไว้ ข้อมูลพิกัดระหว่างเหตุการณ์การลาก
  • ป้องกัน ความขัดแย้งของตัวแปรระหว่างองค์ประกอบที่ลากได้ต่าง ๆ
  • สร้าง โครงสร้างโค้ดที่สะอาดและมีการจัดระเบียบ

🎯 เป้าหมายการเรียนรู้: คุณไม่จำเป็นต้องเข้าใจทุกแง่มุมของ closures ในตอนนี้ มุ่งเน้นที่การเห็นว่ามันช่วยเราในการจัดระเบียบโค้ดและรักษาสถานะสำหรับฟังก์ชันการลากอย่างไร

การสร้างฟังก์ชัน dragElement

ตอนนี้มาสร้างฟังก์ชันหลักที่จะจัดการตรรกะการลากทั้งหมด เพิ่มฟังก์ชันนี้ด้านล่างการประกาศองค์ประกอบต้นไม้ของคุณ:

function dragElement(terrariumElement) {
    // Initialize position tracking variables
    let pos1 = 0,  // Previous mouse X position
        pos2 = 0,  // Previous mouse Y position  
        pos3 = 0,  // Current mouse X position
        pos4 = 0;  // Current mouse Y position
    
    // Set up the initial drag event listener
    terrariumElement.onpointerdown = pointerDrag;
}

ทำความเข้าใจระบบการติดตามตำแหน่ง:

  • pos1 และ pos2: เก็บความแตกต่างระหว่างตำแหน่งเมาส์เก่าและใหม่
  • pos3 และ pos4: ติดตามพิกัดเมาส์ปัจจุบัน
  • terrariumElement: องค์ประกอบต้นไม้เฉพาะที่เรากำลังทำให้ลากได้
  • onpointerdown: เหตุการณ์ที่เริ่มต้นเมื่อผู้ใช้เริ่มลาก

นี่คือวิธีการทำงานของรูปแบบ closure:

  • สร้าง ตัวแปรตำแหน่งส่วนตัวสำหรับองค์ประกอบต้นไม้แต่ละตัว
  • คงไว้ ตัวแปรเหล่านี้ตลอดวงจรการลาก
  • รับรอง ว่าต้นไม้แต่ละต้นติดตามพิกัดของตัวเองอย่างอิสระ
  • ให้ อินเทอร์เฟซที่สะอาดผ่านฟังก์ชัน dragElement

ทำไมต้องใช้ Pointer Events?

คุณอาจสงสัยว่าทำไมเราถึงใช้ onpointerdown แทน onclick ที่คุ้นเคย นี่คือเหตุผล:

ประเภทเหตุการณ์ เหมาะสำหรับ ข้อจำกัด
onclick การคลิกปุ่มง่าย ๆ ไม่สามารถจัดการการลากได้ (แค่คลิกและปล่อย)
onpointerdown ทั้งเมาส์และสัมผัส ใหม่กว่า แต่รองรับได้ดีในปัจจุบัน
onmousedown เฉพาะเมาส์เดสก์ท็อป ไม่รองรับผู้ใช้มือถือ

ทำไม pointer events ถึงเหมาะสำหรับสิ่งที่เรากำลังสร้าง:

  • ทำงานได้ดี ไม่ว่าคนจะใช้เมาส์ นิ้ว หรือแม้กระทั่งปากกา
  • ให้ความรู้สึกเหมือนกัน บนแล็ปท็อป แท็บเล็ต หรือโทรศัพท์
  • จัดการ การเคลื่อนไหวการลากจริง (ไม่ใช่แค่คลิกและเสร็จสิ้น)
  • สร้าง ประสบการณ์ที่ราบรื่นที่ผู้ใช้คาดหวังจากแอปเว็บสมัยใหม่

💡 การเตรียมตัวสำหรับอนาคต: Pointer events เป็นวิธีการจัดการการโต้ตอบของผู้ใช้ในยุคใหม่ แทนที่จะเขียนโค้ดแยกสำหรับเมาส์และสัมผัส คุณจะได้ทั้งสองอย่างฟรี น่าสนใจใช่ไหม?


ฟังก์ชัน pointerDrag: การจับการเริ่มต้นการลาก

เมื่อผู้ใช้กดลงบนต้นไม้ (ไม่ว่าจะด้วยการคลิกเมาส์หรือสัมผัสนิ้ว) ฟังก์ชัน pointerDrag จะเริ่มทำงาน ฟังก์ชันนี้จับพิกัดเริ่มต้นและตั้งค่าระบบการลาก

เพิ่มฟังก์ชันนี้ภายใน closure dragElement หลังบรรทัด terrariumElement.onpointerdown = pointerDrag;:

function pointerDrag(e) {
    // Prevent default browser behavior (like text selection)
    e.preventDefault();
    
    // Capture the initial mouse/touch position
    pos3 = e.clientX;  // X coordinate where drag started
    pos4 = e.clientY;  // Y coordinate where drag started
    
    // Set up event listeners for the dragging process
    document.onpointermove = elementDrag;
    document.onpointerup = stopElementDrag;
}

ทีละขั้นตอน นี่คือสิ่งที่เกิดขึ้น:

  • ป้องกัน พฤติกรรมเริ่มต้นของเบราว์เซอร์ที่อาจรบกวนการลาก
  • บันทึก พิกัดที่แน่นอนที่ผู้ใช้เริ่มต้นการลาก
  • ตั้งค่า event listeners สำหรับการเคลื่อนไหวการลากที่กำลังดำเนินอยู่
  • เตรียม ระบบเพื่อติดตามการเคลื่อนไหวเมาส์/นิ้วทั่วทั้งเอกสาร

ทำความเข้าใจการป้องกันเหตุการณ์

บรรทัด e.preventDefault() มีความสำคัญต่อการลากที่ราบรื่น:

หากไม่มีการป้องกัน เบราว์เซอร์อาจ:

  • เลือก ข้อความเมื่อลากผ่านหน้าเว็บ
  • เรียกใช้ เมนูบริบทเมื่อคลิกขวาและลาก
  • รบกวน พฤติกรรมการลากที่กำหนดเองของเรา
  • สร้าง สิ่งประดิษฐ์ภาพระหว่างการลาก

🔍 ทดลอง: หลังจากจบบทเรียนนี้ ลองลบบรรทัด e.preventDefault() และดูว่ามันส่งผลต่อประสบการณ์การลากอย่างไร คุณจะเข้าใจได้อย่างรวดเร็วว่าทำไมบรรทัดนี้ถึงจำเป็น!

ระบบการติดตามพิกัด

คุณสมบัติ e.clientX และ e.clientY ให้พิกัดเมาส์/สัมผัสที่แม่นยำ:

คุณสมบัติ สิ่งที่วัด กรณีการใช้งาน
clientX ตำแหน่งแนวนอนสัมพันธ์กับ viewport ติดตามการเคลื่อนไหวซ้าย-ขวา
clientY ตำแหน่งแนวตั้งสัมพันธ์กับ viewport ติดตามการเคลื่อนไหวขึ้น-ลง

ทำความเข้าใจพิกัดเหล่านี้:

  • ให้ ข้อมูลตำ
  • pos3 และ pos4: เก็บตำแหน่งเมาส์ปัจจุบันเพื่อใช้ในการคำนวณครั้งถัดไป
  • offsetTop และ offsetLeft: รับตำแหน่งปัจจุบันขององค์ประกอบบนหน้าเว็บ
  • ตรรกะการลบ: ย้ายองค์ประกอบตามระยะที่เมาส์เคลื่อนที่

นี่คือการคำนวณการเคลื่อนไหวแบบละเอียด:

  1. วัด ความแตกต่างระหว่างตำแหน่งเมาส์เก่าและใหม่
  2. คำนวณ ระยะที่ต้องย้ายองค์ประกอบตามการเคลื่อนที่ของเมาส์
  3. อัปเดต คุณสมบัติตำแหน่ง CSS ขององค์ประกอบแบบเรียลไทม์
  4. เก็บ ตำแหน่งใหม่เป็นฐานสำหรับการคำนวณการเคลื่อนไหวครั้งถัดไป

การแสดงภาพของการคำนวณทางคณิตศาสตร์

sequenceDiagram
    participant Mouse
    participant JavaScript
    participant Plant
    
    Mouse->>JavaScript: Move from (100,50) to (110,60)
    JavaScript->>JavaScript: Calculate: moved 10px right, 10px down
    JavaScript->>Plant: Update position by +10px right, +10px down
    Plant->>Plant: Render at new position

ฟังก์ชัน stopElementDrag: การทำความสะอาด

เพิ่มฟังก์ชันการทำความสะอาดหลังปีกกาปิดของ elementDrag:

function stopElementDrag() {
    // Remove the document-level event listeners
    document.onpointerup = null;
    document.onpointermove = null;
}

ทำไมการทำความสะอาดถึงสำคัญ:

  • ป้องกัน การรั่วไหลของหน่วยความจำจากตัวฟังเหตุการณ์ที่ยังค้างอยู่
  • หยุด พฤติกรรมการลากเมื่อผู้ใช้ปล่อยต้นไม้
  • อนุญาต ให้องค์ประกอบอื่นสามารถลากได้อย่างอิสระ
  • รีเซ็ต ระบบสำหรับการดำเนินการลากครั้งถัดไป

สิ่งที่เกิดขึ้นหากไม่มีการทำความสะอาด:

  • ตัวฟังเหตุการณ์ยังคงทำงานแม้หลังจากการลากหยุดลง
  • ประสิทธิภาพลดลงเนื่องจากตัวฟังที่ไม่ได้ใช้งานสะสม
  • พฤติกรรมที่ไม่คาดคิดเมื่อโต้ตอบกับองค์ประกอบอื่น
  • ทรัพยากรของเบราว์เซอร์ถูกใช้ไปกับการจัดการเหตุการณ์ที่ไม่จำเป็น

ทำความเข้าใจคุณสมบัติตำแหน่ง CSS

ระบบการลากของเราจัดการกับคุณสมบัติ CSS หลักสองตัว:

คุณสมบัติ สิ่งที่ควบคุม วิธีการใช้งาน
top ระยะห่างจากขอบด้านบน การจัดตำแหน่งแนวตั้งระหว่างการลาก
left ระยะห่างจากขอบด้านซ้าย การจัดตำแหน่งแนวนอนระหว่างการลาก

ข้อมูลสำคัญเกี่ยวกับคุณสมบัติ offset:

  • offsetTop: ระยะห่างปัจจุบันจากด้านบนขององค์ประกอบแม่ที่มีการกำหนดตำแหน่ง
  • offsetLeft: ระยะห่างปัจจุบันจากด้านซ้ายขององค์ประกอบแม่ที่มีการกำหนดตำแหน่ง
  • บริบทการกำหนดตำแหน่ง: ค่าพวกนี้สัมพันธ์กับบรรพบุรุษที่มีการกำหนดตำแหน่งใกล้ที่สุด
  • การอัปเดตแบบเรียลไทม์: เปลี่ยนแปลงทันทีเมื่อเราปรับคุณสมบัติ CSS

🎯 ปรัชญาการออกแบบ: ระบบการลากนี้มีความยืดหยุ่นโดยตั้งใจ ไม่มี "โซนวาง" หรือข้อจำกัดใดๆ ผู้ใช้สามารถวางต้นไม้ได้ทุกที่ ทำให้พวกเขามีอิสระในการออกแบบสวนขวดของตัวเองอย่างเต็มที่

รวมทุกอย่างเข้าด้วยกัน: ระบบลากของคุณที่สมบูรณ์

ยินดีด้วย! คุณเพิ่งสร้างระบบลากและวางที่ซับซ้อนโดยใช้ JavaScript แบบพื้นฐาน ฟังก์ชัน dragElement ของคุณตอนนี้มี closure ที่ทรงพลังซึ่งจัดการ:

สิ่งที่ closure ของคุณทำได้:

  • รักษา ตัวแปรตำแหน่งส่วนตัวสำหรับต้นไม้แต่ละต้นอย่างอิสระ
  • จัดการ วงจรการลากทั้งหมดตั้งแต่ต้นจนจบ
  • ให้ การเคลื่อนไหวที่ราบรื่นและตอบสนองทั่วทั้งหน้าจอ
  • ทำความสะอาด ทรัพยากรอย่างเหมาะสมเพื่อป้องกันการรั่วไหลของหน่วยความจำ
  • สร้าง อินเทอร์เฟซที่ใช้งานง่ายและสร้างสรรค์สำหรับการออกแบบสวนขวด

ทดสอบสวนขวดแบบโต้ตอบของคุณ

ตอนนี้ทดสอบสวนขวดแบบโต้ตอบของคุณ! เปิดไฟล์ index.html ในเว็บเบราว์เซอร์และลองใช้งาน:

  1. คลิกและกดค้าง ที่ต้นไม้ใดๆ เพื่อเริ่มการลาก
  2. เคลื่อนเมาส์หรือใช้นิ้ว และดูต้นไม้เคลื่อนที่ตามอย่างราบรื่น
  3. ปล่อย เพื่อวางต้นไม้ในตำแหน่งใหม่
  4. ทดลอง จัดเรียงในรูปแบบต่างๆ เพื่อสำรวจอินเทอร์เฟซ

🥇 ความสำเร็จ: คุณได้สร้างแอปพลิเคชันเว็บแบบโต้ตอบเต็มรูปแบบโดยใช้แนวคิดหลักที่นักพัฒนามืออาชีพใช้ในชีวิตประจำวัน ฟังก์ชันการลากและวางนี้ใช้หลักการเดียวกันกับการอัปโหลดไฟล์ กระดานงาน และอินเทอร์เฟซแบบโต้ตอบอื่นๆ อีกมากมาย

finished terrarium


ความท้าทาย GitHub Copilot Agent 🚀

ใช้โหมด Agent เพื่อทำความท้าทายต่อไปนี้ให้สำเร็จ:

คำอธิบาย: ปรับปรุงโครงการสวนขวดโดยเพิ่มฟังก์ชันการรีเซ็ตที่คืนต้นไม้ทั้งหมดไปยังตำแหน่งเดิมด้วยแอนิเมชันที่ราบรื่น

คำสั่ง: สร้างปุ่มรีเซ็ตที่เมื่อคลิกแล้วจะทำให้ต้นไม้ทั้งหมดเคลื่อนกลับไปยังตำแหน่งเดิมในแถบด้านข้างด้วยแอนิเมชัน CSS ที่ราบรื่น ฟังก์ชันควรเก็บตำแหน่งเดิมเมื่อหน้าโหลดและเปลี่ยนต้นไม้กลับไปยังตำแหน่งเหล่านั้นอย่างราบรื่นภายใน 1 วินาทีเมื่อกดปุ่มรีเซ็ต

เรียนรู้เพิ่มเติมเกี่ยวกับ agent mode ที่นี่

🚀 ความท้าทายเพิ่มเติม: ขยายทักษะของคุณ

พร้อมที่จะยกระดับสวนขวดของคุณไปอีกขั้นหรือยัง? ลองเพิ่มฟังก์ชันเหล่านี้:

การขยายความคิดสร้างสรรค์:

  • ดับเบิลคลิก ที่ต้นไม้เพื่อให้มันอยู่ด้านหน้า (การจัดการ z-index)
  • เพิ่มการตอบสนองทางภาพ เช่นแสงเรืองรองเล็กน้อยเมื่อเลื่อนเมาส์ไปที่ต้นไม้
  • กำหนดขอบเขต เพื่อป้องกันไม่ให้ต้นไม้ถูกลากออกนอกสวนขวด
  • สร้างฟังก์ชันบันทึก ที่จดจำตำแหน่งต้นไม้โดยใช้ localStorage
  • เพิ่มเสียงเอฟเฟกต์ เมื่อหยิบและวางต้นไม้

💡 โอกาสในการเรียนรู้: ความท้าทายแต่ละข้อจะช่วยให้คุณเรียนรู้แง่มุมใหม่ๆ เกี่ยวกับการจัดการ DOM การจัดการเหตุการณ์ และการออกแบบประสบการณ์ผู้ใช้

แบบทดสอบหลังการบรรยาย

แบบทดสอบหลังการบรรยาย

ทบทวนและศึกษาด้วยตัวเอง: เพิ่มพูนความเข้าใจของคุณ

คุณได้เชี่ยวชาญพื้นฐานของการจัดการ DOM และ closures แล้ว แต่ยังมีสิ่งที่ต้องสำรวจอีกมากมาย! นี่คือเส้นทางบางส่วนเพื่อขยายความรู้และทักษะของคุณ

วิธีการลากและวางทางเลือก

เราใช้ pointer events เพื่อความยืดหยุ่นสูงสุด แต่การพัฒนาเว็บมีวิธีการหลายแบบ:

วิธีการ เหมาะสำหรับ คุณค่าการเรียนรู้
HTML Drag and Drop API การอัปโหลดไฟล์ โซนลากที่เป็นทางการ ทำความเข้าใจความสามารถของเบราว์เซอร์โดยธรรมชาติ
Touch Events การโต้ตอบเฉพาะมือถือ รูปแบบการพัฒนาสำหรับมือถือเป็นหลัก
คุณสมบัติ CSS transform แอนิเมชันที่ราบรื่น เทคนิคการเพิ่มประสิทธิภาพ

หัวข้อการจัดการ DOM ขั้นสูง

ขั้นตอนต่อไปในเส้นทางการเรียนรู้ของคุณ:

  • Event delegation: การจัดการเหตุการณ์อย่างมีประสิทธิภาพสำหรับองค์ประกอบหลายตัว
  • Intersection Observer: การตรวจจับเมื่อองค์ประกอบเข้าสู่/ออกจากมุมมอง
  • Mutation Observer: การเฝ้าดูการเปลี่ยนแปลงในโครงสร้าง DOM
  • Web Components: การสร้างองค์ประกอบ UI ที่นำกลับมาใช้ใหม่ได้และมีการห่อหุ้ม
  • แนวคิด Virtual DOM: ทำความเข้าใจว่ากรอบงานปรับปรุงการอัปเดต DOM อย่างไร

แหล่งข้อมูลสำคัญสำหรับการเรียนรู้ต่อเนื่อง

เอกสารทางเทคนิค:

ความเข้ากันได้ของเบราว์เซอร์:

  • CanIUse.com - ตรวจสอบการรองรับฟีเจอร์ในเบราว์เซอร์ต่างๆ
  • MDN Browser Compatibility Data - ข้อมูลความเข้ากันได้โดยละเอียด

โอกาสในการฝึกฝน:

  • สร้าง เกมปริศนาโดยใช้กลไกการลากที่คล้ายกัน
  • สร้าง กระดานงานที่มีการจัดการงานแบบลากและวาง
  • ออกแบบ แกลเลอรีภาพที่สามารถจัดเรียงรูปภาพได้ด้วยการลาก
  • ทดลอง กับท่าทางสัมผัสสำหรับอินเทอร์เฟซมือถือ

🎯 กลยุทธ์การเรียนรู้: วิธีที่ดีที่สุดในการทำให้แนวคิดเหล่านี้มั่นคงคือการฝึกฝน ลองสร้างรูปแบบต่างๆ ของอินเทอร์เฟซที่สามารถลากได้ แต่ละโครงการจะสอนสิ่งใหม่ๆ เกี่ยวกับการโต้ตอบของผู้ใช้และการจัดการ DOM

งานที่ได้รับมอบหมาย

ทำงานเพิ่มเติมกับ DOM


ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลโดยอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้