تشرح هذه المشاركة أساسيات السحب والإفلات.
إنشاء محتوى قابل للسحب
في معظم المتصفحات، يمكن سحب تحديدات النصوص والصور والروابط تلقائيًا. على سبيل المثال، إذا سحبت رابطًا على صفحة ويب، فسترى مربعًا صغيرًا يحتوي على عنوان وعنوان URL اللذان يمكنك إفلاتهما في شريط العناوين أو على سطح المكتب لإنشاء الاختصار أو الانتقال إلى الرابط. ولجعل أنواعًا أخرى من المحتوى قابلة للسحب، يمكنك استخدام واجهات برمجة تطبيقات السحب والإفلات في HTML5.
لإتاحة سحب كائن، اضبط draggable=true
على هذا العنصر. تقريبًا
فيمكن أن يكون أي شيء مع تمكين السحب، بما في ذلك الصور والملفات والروابط والملفات أو أي
الترميز على صفحتك.
ينشئ المثال التالي واجهة لإعادة ترتيب الأعمدة التي
الموضوعة باستخدام CSS Grid. يبدو الترميز الأساسي للأعمدة على هذا النحو،
السمة draggable
لكل عمود تم ضبطه على 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>
في ما يلي CSS لعنصرَي الحاوية والمربّع. خدمة CSS الوحيدة المرتبطة
ميزة السحب هي cursor: move
الموقع. يتحكم باقي الرمز في تنسيق الحاوية وتصميمها
وعناصر المربع.
.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;
}
في هذه المرحلة، يمكنك سحب العناصر، ولكن لا يحدث شيء آخر. للإضافة المستخدم، فإنك تحتاج إلى استخدام واجهة برمجة تطبيقات JavaScript.
الاستماع إلى أحداث السحب
لمراقبة عملية السحب، يمكنك رصد أي من الأحداث التالية:
للتعامل مع تدفق السحب، تحتاج إلى نوع من عنصر المصدر (حيث يكون السحب وحمولة البيانات (الشيء الذي يتم سحبه) والهدف (منطقة والحصول على الانخفاض). يمكن أن يكون العنصر المصدر أي نوع من العناصر تقريبًا. تشير رسالة الأشكال البيانية الهدف هو منطقة الانخفاض أو مجموعة مناطق الانخفاض التي تقبل البيانات التي يستخدمها المستخدم يحاول الهبوط. لا يمكن أن تكون جميع العناصر أهدافًا. على سبيل المثال، لا يمكن للاستهداف صورة.
بدء تسلسل سحب وإنهائه
بعد تحديد سمات draggable="true"
في المحتوى الخاص بك، عليك إرفاق
معالِج أحداث dragstart
لبدء تسلسل السحب لكل عمود
يضبط هذا الرمز معدل شفافية العمود على 40٪ عندما يبدأ المستخدم في سحبه، ثم إرجاعه إلى 100% عند انتهاء حدث السحب.
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);
});
ويمكن الاطّلاع على النتيجة في العرض التوضيحي التالي لتطبيق Glitch. سحب عنصر
تغييرات التعتيم. ولأن العنصر المصدر يحتوي على الحدث dragstart
، فقد تم ضبط إعداد
تقدم نسبة this.style.opacity
إلى 40٪ للمستخدم ملاحظات مرئية أن هذا العنصر
التحديد الحالي الذي يتم نقله. عند إسقاط العنصر، يتم عرض عنصر المصدر
يعود إلى معدل تعتيم 100%، على الرغم من أنك لم تحدد سلوك الانخفاض في الوقت الحالي.
إضافة إشارات مرئية أخرى
لمساعدة المستخدم في فهم كيفية التفاعل مع واجهتك، استخدِم
معالِجات أحداث dragenter
وdragover
وdragleave
في هذا المثال، تشير
والأعمدة هي أهداف للإفلات بالإضافة إلى كونها قابلة للسحب. ساعد المستخدم في
فهم ذلك عن طريق جعل الحدود متقطعة عندما تحمل عنصرًا تم سحبه فوق
. على سبيل المثال، في خدمة مقارنة الأسعار (CSS)، يمكنك إنشاء فئة over
العناصر التي تُعدّ أهدافًا الانخفاض:
.box.over {
border: 3px dotted #666;
}
بعد ذلك، يمكنك إعداد معالِجات الأحداث في JavaScript وإضافة الفئة over
عند
يتم سحب العمود وإزالته عندما يغادر العنصر الذي تم سحبه. ضِمن
إلى معالج dragend
، نحرص أيضًا على إزالة الفئات في نهاية
السحب.
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);
});
});
هناك عدة نقاط تستحق تناولها في هذه التعليمة البرمجية:
الإجراء التلقائي بالنسبة إلى الحدث
dragover
هو ضبط الخاصيةdataTransfer.dropEffect
على"none"
وسنتناول السمةdropEffect
لاحقًا في هذه الصفحة. في الوقت الحالي، فقط، اعلم أنه يمنع تنشيط حدثdrop
. لإلغاء هذا السلوك، طلبe.preventDefault()
. هناك ممارسة جيدة أخرى وهي عرضfalse
في المعالج نفسه.يُستخدَم معالج أحداث
dragenter
لتبديل الفئةover
بدلاً منdragover
في حال استخدامdragover
، يتم تنشيط الحدث بشكل متكرّر أثناء استخدام المستخدِم. تحتفظ بالعنصر المسحوب فوق عمود، مما يتسبب في تبديل فئة CSS بشكل متكرر. يؤدي ذلك إلى إجراء المتصفّح الكثير من أعمال العرض غير الضرورية، مما قد يؤثر على تجربة المستخدم. نوصي بشدة بتقليل وإعادة الرسم، وإذا كنت بحاجة إلى استخدامdragover
، يمكنك تقييد أداة معالجة الحدث أو إقلاعها
إكمال عملية الهبوط
لمعالجة عملية الانخفاض، أضِف أداة معالجة حدث drop
. في drop
فستحتاج إلى منع السلوك الافتراضي للمتصفح لعمليات الإزالة،
يكون عادةً نوعًا من عمليات إعادة التوجيه المزعجة. ولإجراء ذلك، اتّصِل بالرقم e.stopPropagation()
.
function handleDrop(e) {
e.stopPropagation(); // stops the browser from redirecting.
return false;
}
تأكد من تسجيل المعالج الجديد إلى جانب المعالجات الأخرى:
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);
});
إذا شغّلت الرمز في هذه المرحلة، لن يتم إسقاط العنصر في الموقع الجديد. إلى
لتحقيق ذلك، استخدِم DataTransfer
الخاص بك.
تحتفظ السمة dataTransfer
بالبيانات المُرسَلة في إجراء سحب. dataTransfer
يتم ضبطها في الحدث dragstart
وتتم قراءتها أو معالجتها في حدث الإفلات. إجراء المكالمات
يتيح لك "e.dataTransfer.setData(mimeType, dataPayload)
" ضبط بروتوكول MIME للكائن
النوع وحمولة البيانات.
في هذا المثال، سنسمح للمستخدمين بإعادة ترتيب الأعمدة. للقيام بذلك، تحتاج أولاً إلى تخزين HTML للعنصر المصدر عند سحب تبدأ في:
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
في الحدث drop
، يمكنك معالجة انخفاض العمود من خلال ضبط قيمة
HTML في HTML للعمود المستهدف الذي خفضت البيانات إليه. هذا النمط
التحقق من أن المستخدم لا يعود إلى نفس العمود الذي
سحبها منه.
function handleDrop(e) {
e.stopPropagation();
if (dragSrcEl !== this) {
dragSrcEl.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
}
يمكنك مشاهدة النتيجة في العرض التوضيحي التالي. لكي ينجح ذلك، ستحتاج إلى متصفح سطح المكتب. لا تتوفّر واجهة برمجة التطبيقات "السحب والإفلات" على الأجهزة الجوّالة. السحب حرر العمود A أعلى العمود B ولاحظ كيف تغير الأماكن:
المزيد من خصائص السحب
يعرض الكائن dataTransfer
السمات لتقديم ملاحظات مرئية إلى
المستخدم أثناء عملية السحب والتحكم في كيفية استجابة كل هدف إفلات
لنوع بيانات معين.
dataTransfer.effectAllowed
يقيد "نوع السحب" يمكن للمستخدم تنفيذها على العنصر. إنها مُستخدَمة في نموذج معالجة السحب والإفلات لإعدادdropEffect
أثناء حدثينdragenter
وdragover
. يمكن أن يتضمّن الموقع القيم التالية:none
،copy
،copyLink
،copyMove
،link
،linkMove
،move
وall
وuninitialized
.dataTransfer.dropEffect
تتحكّم هذه السياسة في الملاحظات التي يتلقّاها المستخدم خلالdragenter
وdragover
. أحداث. عندما يمسك المستخدم بالمؤشر فوق عنصر هدف، فإن واجهة يشير المؤشر إلى نوع العملية التي ستحدث، مثل نسخ أو حركة. يمكن أن يحصل التأثير على إحدى القيم التالية:none
أوcopy
أوlink
،move
.e.dataTransfer.setDragImage(imgElement, x, y)
بمعنى أنه بدلاً من استخدام "صورة شبح" الافتراضية في المتصفح الملاحظات، تعيين أيقونة السحب.
تحميل ملف
يستخدم هذا المثال البسيط عمودًا باعتباره مصدر السحب وهدف السحب. هذا النمط في واجهة مستخدم تطلب من المستخدم إعادة ترتيب العناصر. في بعض الحالات، قد يكون هدف السحب والمصدر أنواع عناصر مختلفة، كما هو الحال في الواجهة حيث يحتاج المستخدم إلى اختيار صورة واحدة كصورة رئيسية للمنتج عن طريق سحب الصورة المحددة إلى الهدف.
يتم استخدام السحب والإفلات بشكل متكرر للسماح للمستخدمين بسحب العناصر من سطح المكتب إلى
أحد التطبيقات. يكمن الاختلاف الرئيسي في معالِج drop
. بدلاً من استخدام
dataTransfer.getData()
للوصول إلى الملفات، يتم تضمين بياناتها في
السمة 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.
}
}
يمكنك العثور على مزيد من المعلومات حول هذا الموضوع في السحب والإفلات المخصّص: