Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> HTML

เหตุการณ์ ondrag: รันสคริปตขณะองค์ประกอบถูกลาก (Dragging)

เหตุการณ์ ondrag จะถูกกระตุ้น ซ้ำๆ ตลอดการลาก (Drag) องค์ประกอบ ใช้สำหรับอัปเดต UI แบบเรียลไทม์ขณะลาก ต่างจาก ondragstart (เริ่มลาก) และ ondragend (จบการลาก)

ตัวอย่างการใช้งาน (Drag & Drop ครบวงจร)

<!DOCTYPE HTML>
<html>
<head>
    <style>
        .drag-zone {
            float: left; width: 150px; height: 150px;
            border: 2px dashed #876587; margin: 15px; padding: 10px;
            background: #fafafa; transition: background 0.2s;
        }
        .drag-zone.drag-over { background: #e8f5e9; border-color: #4CAF50; }
        .draggable { background: #4CAF50; color: white; padding: 15px; text-align: center; cursor: grab; }
        #status { clear: both; padding: 15px; background: #fff3e0; font-family: monospace; }
    </style>
</head>
<body>
    <div class="drag-zone" id="zone1" ondrop="drop(event)" ondragover="dragOver(event)" ondragleave="dragLeave(event)">
        <p id="dragItem" draggable="true" 
           ondragstart="dragStart(event)" 
           ondrag="dragging(event)" 
           class="draggable">ลากฉันได้</p>
    </div>
    
    <div class="drag-zone" id="zone2" ondrop="drop(event)" ondragover="dragOver(event)" ondragleave="dragLeave(event)">
        <p>พื้นที่วางเป้าหมาย</p>
    </div>
    
    <div id="status">พร้อมลาก...</div>
    
    <script>
        let dragCount = 0;
        
        function dragStart(e) {
            e.dataTransfer.setData("text/plain", e.target.id);
            e.dataTransfer.effectAllowed = "move";
            e.target.style.opacity = "0.5";
            dragCount = 0;
        }
        
        function dragging(e) {
            dragCount++;
            // Throttle log (ทุก 50 ครั้ง ~ ทุก ~1 วินาที)
            if (dragCount % 50 === 0) {
                document.getElementById('status').textContent = `กำลังลาก... (${dragCount} events)`;
            }
        }
        
        function dragOver(e) {
            e.preventDefault(); // สำคัญ!
            e.dataTransfer.dropEffect = "move";
            e.currentTarget.classList.add('drag-over');
        }
        
        function dragLeave(e) {
            e.currentTarget.classList.remove('drag-over');
        }
        
        function drop(e) {
            e.preventDefault();
            e.currentTarget.classList.remove('drag-over');
            const id = e.dataTransfer.getData("text/plain");
            const el = document.getElementById(id);
            e.currentTarget.appendChild(el);
            el.style.opacity = "1";
            document.getElementById('status').textContent = `วางสำเร็จ! (Drag events: ${dragCount})`;
        }
    </script>
</body>
</html>

เหตุการณ์ Drag Source (ลำดับ)

  1. ondragstart - เริ่มลาก (ตั้งค่า DataTransfer)
  2. ondrag - กำลังลาก (ยิงซ้ำๆ ทุก Frame) ⚡
  3. ondragend - จบการลาก (ทำความสะอาด, Reset UI)

⚠️ ประสิทธิภาพ ondrag

  • ยิง ทุก Animation Frame (~60fps) ขณะลาก
  • ❌ ไม่ควรทำงานหนัก (DOM Manipulation, Layout, Network) ใน Handler
  • ✅ ใช้ requestAnimationFrame หรือ Throttle (100-200ms)
  • ✅ ใช้สำหรับ: Update Visual Feedback (Coordinates, Preview), Simple Calculations

ตัวอย่าง Throttle สำหรับ ondrag

function throttle(fn, delay) {
    let lastCall = 0;
    return function(...args) {
        const now = Date.now();
        if (now - lastCall >= delay) {
            lastCall = now;
            fn.apply(this, args);
        }
    };
}

const throttledDrag = throttle((e) => {
    // อัปเดต UI Position Preview
    updateDragPreview(e.clientX, e.clientY);
}, 50); // 20fps

element.ondrag = throttledDrag;