Postingan ini menjelaskan dasar-dasar tarik lalu lepas.
Membuat konten yang dapat ditarik
Di sebagian besar browser, pilihan teks, gambar, dan link dapat ditarik secara default. Misalnya, jika menarik link di halaman web, Anda akan melihat kotak kecil dengan judul dan URL yang dapat Anda lepaskan di kolom URL atau desktop untuk membuat pintasan atau membuka link. Agar jenis konten lainnya dapat ditarik, Anda harus menggunakan HTML5 Drag and Drop API.
Untuk membuat objek dapat ditarik, tetapkan draggable=true
pada elemen tersebut. Hampir semua
hal dapat ditarik, termasuk gambar, file, link, file, atau markup
apa pun di halaman Anda.
Contoh berikut membuat antarmuka untuk mengatur ulang kolom yang telah
ditata dengan CSS Grid. Markup dasar untuk kolom terlihat seperti ini, dengan
atribut draggable
untuk setiap kolom ditetapkan ke true
:
<div class="container">
<div draggable="true" class="box">A</div>
<div draggable="true" class="box">B</div>
<div draggable="true" class="box">C</div>
</div>
Berikut adalah CSS untuk elemen penampung dan kotak. Satu-satunya CSS yang terkait dengan
fitur tarik adalah properti
cursor: move
. Kode lainnya mengontrol tata letak dan gaya elemen penampung
dan kotak.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.box {
border: 3px solid #666;
background-color: #ddd;
border-radius: .5em;
padding: 10px;
cursor: move;
}
Pada tahap ini, Anda dapat menarik item, tetapi tidak ada yang terjadi. Untuk menambahkan perilaku, Anda perlu menggunakan JavaScript API.
Memproses peristiwa tarik
Untuk memantau proses tarik, Anda dapat memproses salah satu peristiwa berikut:
Untuk menangani alur tarik, Anda memerlukan semacam elemen sumber (tempat tarik dimulai), payload data (hal yang ditarik), dan target (area untuk menangkap drop). Elemen sumber dapat berupa hampir semua jenis elemen. Target adalah zona lepas atau sekumpulan zona lepas yang menerima data yang coba dilepas pengguna. Tidak semua elemen dapat menjadi target. Misalnya, target Anda tidak boleh berbentuk gambar.
Memulai dan mengakhiri urutan tarik
Setelah menentukan atribut draggable="true"
pada konten, lampirkan
pengendali peristiwa dragstart
untuk memulai urutan tarik untuk setiap kolom.
Kode ini menetapkan opasitas kolom ke 40% saat pengguna mulai menariknya, lalu mengembalikannya ke 100% saat peristiwa penarikan berakhir.
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
}
let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragend', handleDragEnd);
});
Hasilnya dapat dilihat di demo Glitch berikut. Tarik item, dan
opasinya akan berubah. Karena elemen sumber memiliki peristiwa dragstart
, menetapkan
this.style.opacity
ke 40% akan memberi pengguna masukan visual bahwa elemen tersebut adalah
pilihan saat ini yang dipindahkan. Saat Anda melepas item, elemen sumber
akan kembali ke opasitas 100%, meskipun Anda belum menentukan perilaku lepas.
Menambahkan isyarat visual tambahan
Untuk membantu pengguna memahami cara berinteraksi dengan antarmuka Anda, gunakan
pengendali peristiwa dragenter
, dragover
, dan dragleave
. Dalam contoh ini, kolom adalah target drop selain dapat ditarik. Bantu pengguna untuk memahami hal ini dengan membuat batas putus-putus saat mereka menahan item yang ditarik di atas kolom. Misalnya, di CSS, Anda dapat membuat class over
untuk elemen yang merupakan target drop:
.box.over {
border: 3px dotted #666;
}
Kemudian, di JavaScript, siapkan pengendali peristiwa, tambahkan class over
saat
kolom ditarik, dan hapus saat elemen yang ditarik keluar. Di
pengendali dragend
, kita juga memastikan untuk menghapus class di akhir
tarik.
document.addEventListener('DOMContentLoaded', (event) => {
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
items.forEach(function (item) {
item.classList.remove('over');
});
}
function handleDragOver(e) {
e.preventDefault();
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
});
Ada beberapa poin yang perlu dibahas dalam kode ini:
Tindakan default untuk peristiwa
dragover
adalah menetapkan propertidataTransfer.dropEffect
ke"none"
. PropertidropEffect
akan dibahas nanti di halaman ini. Untuk saat ini, cukup ketahui bahwa tindakan ini mencegah peristiwadrop
diaktifkan. Untuk mengganti perilaku ini, panggile.preventDefault()
. Praktik baik lainnya adalah menampilkanfalse
di pengendali yang sama.Pengendali peristiwa
dragenter
digunakan untuk mengalihkan classover
, bukandragover
. Jika Anda menggunakandragover
, peristiwa akan diaktifkan berulang kali saat pengguna memegang item yang ditarik di atas kolom, sehingga class CSS akan beralih berulang kali. Hal ini membuat browser melakukan banyak pekerjaan rendering yang tidak perlu, yang dapat memengaruhi pengalaman pengguna. Sebaiknya minimalkan penggambaran ulang, dan jika Anda perlu menggunakandragover
, pertimbangkan pembatasan atau debouncing pemroses peristiwa.
Menyelesaikan drop
Untuk memproses drop, tambahkan pemroses peristiwa untuk peristiwa drop
. Di pengendali drop
, Anda harus mencegah perilaku default browser untuk drop, yang
biasanya merupakan semacam pengalihan yang mengganggu. Untuk melakukannya, panggil e.stopPropagation()
.
function handleDrop(e) {
e.stopPropagation(); // stops the browser from redirecting.
return false;
}
Pastikan untuk mendaftarkan pengendali baru bersama pengendali lainnya:
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
Jika Anda menjalankan kode pada tahap ini, item tidak akan dihapus ke lokasi baru. Untuk
melakukannya, gunakan objek
DataTransfer
.
Properti dataTransfer
menyimpan data yang dikirim dalam tindakan tarik. dataTransfer
ditetapkan dalam peristiwa dragstart
dan dibaca atau ditangani dalam peristiwa drop. Dengan memanggil
e.dataTransfer.setData(mimeType, dataPayload)
, Anda dapat menetapkan jenis MIME
dan payload data objek.
Dalam contoh ini, kita akan mengizinkan pengguna mengatur ulang urutan kolom. Untuk melakukannya, Anda harus menyimpan HTML elemen sumber terlebih dahulu saat proses tarik dimulai:
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
Dalam peristiwa drop
, Anda memproses drop kolom dengan menetapkan HTML kolom sumber
ke HTML kolom target tempat Anda meletakkan data. Hal ini
termasuk memeriksa apakah pengguna tidak meletakkan kembali ke kolom yang sama dengan
kolom yang mereka tarik.
function handleDrop(e) {
e.stopPropagation();
if (dragSrcEl !== this) {
dragSrcEl.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
}
Anda dapat melihat hasilnya dalam demo berikut. Agar dapat berfungsi, Anda memerlukan browser desktop. API Tarik lalu Lepaskan tidak didukung di perangkat seluler. Tarik lalu lepaskan kolom A di atas kolom B dan perhatikan bagaimana posisinya berubah:
Properti menarik lainnya
Objek dataTransfer
mengekspos properti untuk memberikan masukan visual kepada
pengguna selama proses tarik dan mengontrol cara setiap target lepas merespons
jenis data tertentu.
dataTransfer.effectAllowed
membatasi 'jenis tarik' yang dapat dilakukan pengguna pada elemen. Fungsi ini digunakan dalam model pemrosesan tarik lalu lepas untuk melakukan inisialisasidropEffect
selama peristiwadragenter
dandragover
. Properti ini dapat memiliki nilai berikut:none
,copy
,copyLink
,copyMove
,link
,linkMove
,move
,all
, danuninitialized
.dataTransfer.dropEffect
mengontrol masukan yang diperoleh pengguna selama peristiwadragenter
dandragover
. Saat pengguna menahan kursor di atas elemen target, kursor browser akan menunjukkan jenis operasi yang akan dilakukan, seperti menyalin atau memindahkan. Efek dapat menggunakan salah satu nilai berikut:none
,copy
,link
,move
.e.dataTransfer.setDragImage(imgElement, x, y)
berarti bahwa Anda dapat menetapkan ikon tarik, bukan menggunakan masukan 'gambar hantu' default browser.
Upload file
Contoh sederhana ini menggunakan kolom sebagai sumber tarik dan target tarik. Hal ini mungkin terjadi di UI yang meminta pengguna untuk menyusun ulang item. Dalam beberapa situasi, target dan sumber tarik mungkin merupakan jenis elemen yang berbeda, seperti pada antarmuka tempat pengguna perlu memilih satu gambar sebagai gambar utama untuk produk dengan menarik gambar yang dipilih ke target.
Tarik lalu lepas sering digunakan untuk memungkinkan pengguna menarik item dari desktop ke
aplikasi. Perbedaan utamanya ada pada pengendali drop
Anda. Datanya tidak disimpan dalam properti dataTransfer.getData()
untuk mengakses file, tetapi disimpan dalam properti dataTransfer.files
:
function handleDrop(e) {
e.stopPropagation(); // Stops some browsers from redirecting.
e.preventDefault();
var files = e.dataTransfer.files;
for (var i = 0, f; (f = files[i]); i++) {
// Read the File objects in this FileList.
}
}
Anda dapat menemukan informasi selengkapnya tentang hal ini di Tarik lalu lepas kustom.