Загальні питання та теорія технології Drag and Drop. Технологія Drag and Drop в Android Дивитись що таке "Drag-and-drop" в інших словниках

182

У цьому прикладі ми вибираємо елемент div і робимо його, що переміщується шляхом виклику для нього методу draggable() . Як показано на малюнку нижче, у документі елемент займає свою звичайну позицію, але після цього його можна перемістити за допомогою покажчика миші в будь-яке місце у вікні браузера:

Можливість перетягування елементів корисна вже сама по собі, але вона приносить ще більше користі, якщо застосовується у поєднанні із взаємодією Droppable, яка описана далі.

Взаємодія Draggable реалізується виключно за рахунок використання специфічної HTML-розмітки та CSS-стилів. Це означає, що ця функціональність працюватиме практично в будь-якому браузері, але наділені нею елементи не зможуть працювати з аналогічними власними засобами Drag-and-drop операційних систем.

Операції Drag-and-drop, що визначаються специфікацією HTML5 операції, зазвичай реалізуються з використанням власних механізмів операційних систем. Якщо ви використовуєте механізм Drag-and-drop jQuery UI, то, щоб уникнути конфліктних ситуацій, еквівалентні засоби HTML5 краще відключити. Для цього встановіть для атрибуту draggable елемента body документа значення false.

Налагодження взаємодії Draggable

Існує безліч опцій налаштування для взаємодії Draggable. Найбільш важливі властивості, розгляд яких присвячені наступні розділи, наведені в таблиці нижче:

Властивості взаємодії Draggable Властивість Опис
axis Обмежує можливості переміщення певними напрямами. Значення за промовчанням - false, воно означає відсутність обмежень, але можна також вказати значення "x" (переміщення лише вздовж осі X) або "y" (переміщення лише вздовж осі Y)
containment Обмежує розташування елемента, що переміщується, певною областю екрана. Типи значень, що підтримуються, описані в таблиці нижче, при розгляді відповідного прикладу. Значення за промовчанням – false, воно означає відсутність обмежень
delay Визначає час, протягом якого має здійснюватись перетягування елемента, перш ніж він переміститься. Значення за замовчуванням – 0, воно означає відсутність затримки
distance Визначає відстань, на яку користувач повинен перетягнути елемент з його початкової позиції, перш ніж він переміститься. Значення за замовчуванням – 1 піксель
grid Здійснює примусову прив'язку елемента, що переміщається до осередків сітки. Значення за промовчанням – false, воно означає відсутність прив'язки
Обмеження напрямків переміщення

Існує кілька способів, за допомогою яких можна обмежити переміщення елемента певними напрямками. Перший полягає у використанні опції axis, що дозволяє обмежити напрямок переміщення віссю X чи Y. Відповідний приклад наведено нижче:

... div.dragElement (font-size: large; border: thin solid black; padding:16px; width: 8em; text-align: center; background-color: lightgray; margin: 4px ) $(function() ( $ (".dragElement").draggable(( axis: "x" )).filter("#dragV").draggable("option", "axis", "y"); )); Перетягнути по вертикалі Перетягнути по горизонталі Запустити приклад

У цьому прикладі ми визначаємо два елементи div, вибираємо їх за допомогою jQuery та викликаємо метод draggable(). Як аргумент цього методу передається об'єкт, який спочатку обмежує переміщення обох елементів div напрямком вздовж осі X. Застосувавши потім метод jQuery filter(), ми отримуємо можливість вибрати елемент dragV без повторного пошуку засобами jQuery по всьому документу і встановити для нього інший дозволений напрямок переміщення - вздовж осі Y. Таким чином, ми отримуємо документ, в якому один елемент div можна перетягувати лише у вертикальному напрямку, а інший – лише у горизонтальному. Результат представлений малюнку:

Обмеження допустимої області переміщення елемента

Можна також обмежити область екрана, в якій можна перетягувати елемент. Для цього використовується опція containment. Формати значень, які можна вказувати в цій опції, описані в таблиці нижче:

Приклад використання опції containment наведено нижче:

... div.dragElement (font-size: large; border: thin solid black; padding:16px; width: 8em; text-align: center; background-color: lightgray; margin: 4px ) #container ( border: medium double black; width: 700px; height: 450px) $(function() ( $(".dragElement").draggable(( containment: "parent" )).filter("#dragH").draggable("option", " axis", "x"); )); Перетягнути по горизонталі Перетягнути всередині батька Запустити приклад

У цьому прикладі можливості переміщення обох елементів обмежені таким чином, що їх можна перетягувати тільки всередині батьківського елемента, як виступає елемент div з фіксованими розмірами. Для одного з елементів div, що переміщуються, за допомогою опції axis введено додаткове обмеження, що полягає в тому, що він може переміщатися всередині батьківського елемента тільки в горизонтальному напрямку. Результат проілюстрований на малюнку:

Обмеження можливостей переміщення елемента осередками сітки

Опція grid дозволяє задати прив'язку елемента, що переміщається, до осередків сітки. Ця опція приймає як значення масив з двох елементів, що визначають ширину та висоту осередків сітки в пікселях. Приклад використання опції grid наведено нижче:

... #draggable (font-size: x-large; border: thin solid black; width: 5em; text-align: center; padding:10px) $(function() ( $("#draggable").draggable( (Grid:));)); Перетягніть мене Запустити приклад

У цьому прикладі задана сітка з осередками шириною 100 пікселів та висотою 50 пікселів. Коли ви перетягуєте елемент, він "перескакується" з одного (невидимого) осередку до іншого. Ефект прив'язки є дуже показовим прикладом використання функціональності взаємодій, проте його важко передати за допомогою екранних знімків.

Можна створити ефект прив'язки лише для одного напрямку, вказавши для осі вільного переміщення значення 1. Наприклад, якщо присвоїти опції grid значення , то елемент буде прив'язуватися до осередків сітки шириною 100 пікселів при переміщенні по горизонталі, але переміщення по вертикалі буде вільним.

Затримка переміщення

Існують дві опції, що дозволяють організувати затримку при перетягуванні елемента, що переміщається. За допомогою опції delay можна встановити час у мілісекундах, протягом якого користувач повинен перетягувати покажчик миші, перш ніж елемент буде дійсно переміщений. Інший вид затримки забезпечується опцією distance, що визначає відстань у пікселях, на яку користувач повинен перетягнути покажчик миші, перш ніж за ним піде елемент.

Приклад використання обох налаштувань наведено нижче:

... #time, #distance (font-size: large; border: thin solid black; padding: 10px; width: 120px; text-align: center; background-color: lightgray; margin: 4px; ) $(function( ) ( $("#time").draggable(( delay: 1000 )) $("#distance").draggable(( distance: 150 )) )); Блок із затримкою часу Блок із мінімальною відстанню Запустити приклад

У цьому прикладі є два елементи, що переміщаються, для одного з яких затримка задана за допомогою опції delay, а для іншого - за допомогою опції distance.

У разі затримки, яка визначається опцією delay, користувач повинен виконувати перетягування протягом заданого часу, перш ніж це призведе до дійсного переміщення елемента. У цьому прикладі тривалість цього проміжку становить 1000 мс. Переміщати мишу в цей час зовсім не обов'язково, але протягом всього періоду затримки кнопка миші повинна залишатися в натиснутому стані, після чого елемент можна буде перемістити, зрушивши мишу. Після закінчення часу затримки елемент, що переміщається, прив'яжеться до розташування покажчика миші з урахуванням обмежень, що накладаються опціями grid, region і axis, про які раніше говорилося.

Опція distance має схожу дію, але в цьому випадку користувач повинен перетягнути покажчик миші не менше ніж на задану кількість пікселів у будь-якому напрямку від початкового розташування елемента. Після цього елемент, що переміщається, стрибкоподібно переміститься до поточного розташування покажчика.

Якщо застосувати обидві налаштування одному й тому елементу, то переміщуваний елемент не зрушить з місця до того часу, доки будуть виконані обидва критерію затримки, тобто. поки спроба перетягування елемента не триватиме протягом заданого часу і поки покажчик миші не переміститься на задану кількість пікселів.

Використання методів взаємодії Draggable

Усі методи, визначені для взаємодії Draggable, входять у набір базових методів, із якими ви вже познайомилися під час розгляду віджетів. Методи, специфічні для взаємодії Draggable, не передбачені, тому ми не розглядатимемо їх докладно. Перелік доступних методів наведено в таблиці нижче:

Використання подій взаємодії Draggable

Взаємодія Draggable підтримує простий набір подій, що повідомляють про перетягування елемента. Ці події описані в таблиці нижче:

Як і у випадку віджетів, на ці події також можна реагувати. Приклад обробки подій start і stop наведено нижче:

... #draggable (font-size: x-large; border: thin solid black; width: 190px; text-align: center; padding:10px) $(function() ( $("#draggable").draggable( ( start: function() ( $("#draggable").text("Перетягування...") ), stop: function() ( $("#draggable").text("Перетягни мене") ) )) ;)); Перетягніть мене Запустити приклад

У цьому прикладі події start і stop використовуються для зміни вмісту тексту в процесі перетягування. Ця сприятлива можливість є наслідком того, що взаємодія Draggable реалізована виключно з використанням засобів HTML і CSS: можна використовувати jQuery для зміни стану елемента, що переміщується навіть у той час, коли він рухається по екрану.

Використання взаємодії Droppable

У деяких ситуаціях лише можливості перетягування елемента може бути цілком достатньо, але найбільшу користь воно приносить у тих випадках, коли використовується спільно з взаємодією Droppable.

Елементи, до яких була застосована взаємодія Droppable (приймають елементи), набувають здатності приймати елементи, що переміщуються, створені за допомогою взаємодії Draggable.

Приймаючі елементи створюються за допомогою методу droppable() , але для отримання корисної функціональності потрібно створити обробники подій з тих, які визначені для цього виду взаємодії. Доступні події наведені в таблиці нижче:

Події взаємодії Droppable Подія Опис
create Відбувається у момент застосування взаємодії Droppable до елементу
activate Відбувається, коли користувач починає перетягувати елемент, що переміщається
deactivate Відбувається, коли користувач припиняє перетягувати елемент, що переміщається
over Відбувається, коли користувач перетягує елемент, що переміщається над приймаючим елементом (але за умови, що кнопка миші ще не була відпущена)
out Відбувається, коли користувач перетягує елемент, що переміщається за межі приймаючого елемента
drop Відбувається, коли користувач залишає елемент, що переміщається на приймаючому елементі

Приклад створення простого приймаючого елемента, для якого визначено єдиного обробника події drop, наведено нижче:

... #draggable, #droppable (font-size: large; border: thin solid black; padding: 10px; width: 100px; text-align: center; background-color: lightgray; margin: 4px;) : 20px; position: absolute; right: 5px;) $(function() ( $("#draggable").draggable(); $("#droppable").droppable(( drop: function() #draggable").text("Залишено") ) )); )); Залиш тут Перетягни мене Запустити приклад

У цьому прикладі документ містить елемент div, текстовий вміст якого представлений рядком "Залиш тут". Ми вибираємо цей елемент, використовуючи jQuery, і викликаємо метод droppable(), передаючи об'єкт з налаштуваннями, який визначає обробник для події drop. Відповіддю на цю подію є зміна тексту елемента, що переміщується за допомогою методу text().

Інтерактивна взаємодія категорії Drag-and-drop, що створюється в даному прикладі, є найпростішою, але вона створює зручний контекст для пояснення можливостей спільної роботи взаємодій Draggable і Droppable. Різні стадії процесу перетягування елементів проілюстровані малюнку:

Все це дуже просто. Ми перетягуємо елемент, що переміщається, доки він не опиниться над приймаючим елементом, і відпускаємо його. Елемент, що переміщається, залишається там, де він був залишений, і його текстовий вміст змінюється у відповідь на наступ події drop. У наступних розділах показано, як використовувати інші події взаємодії Droppable для підвищення комфортності роботи користувача.

Підсвічування цільового приймаючого об'єкта

Використовуючи події activate і deactivate, можна підсвітити цільовий об'єкт, що приймає, коли користувач починає процес перетягування елемента. У багатьох ситуаціях ця ідея виявляється дуже плідною, оскільки користувач отримує надійну вказівку щодо того, які елементи є частиною моделі Drag-and-drop. Відповідний приклад наведено нижче:

... $(function() ( $("#draggable").draggable(); $("#droppable").droppable(( drop: function() ( $("#draggable").text("Залишено) ") ), activate: function() ( $("#droppable").css(( border: "medium double green", backgroundColor: "lightGreen" ));)), deactivate: function() ( $("#droppable ").css("border", "").css("background-color", ""); ) )); )); ... Запустити приклад

Як тільки користувач починає перетягувати елемент, спрацює подія activate - пов'язана з нашим приймаючим елементом, і функція-обробник використовує метод css() для зміни CSS-властивостей border та background-color цього елемента. В результаті цільовий приймаючий елемент підсвічується, вказуючи користувачу на існування зв'язку між ним і елементом, що переміщається.

Подія deactivate використовується для видалення значень CSS-властивостей з приймаючого елемента та його повернення в вихідний станяк тільки користувач відпускає кнопку миші. (Ця подія відбувається щоразу, коли перетягування елемента припиняється, незалежно від того, чи залишений елемент, що переміщається, на приймаючому елементі або не залишений.) Цей процес проілюстрований на малюнку:

Обробка перекривання елементів

Технологію Drag-and-drop можна вдосконалити, додавши до неї обробку подій over і out. Подія over відбувається, коли 50% переміщуваного елемента виявляється над будь-якою частиною елемента, що приймає. Подія out настає тоді, коли елементи, що перекривалися раніше, перестають перекриватися. Приклад реакції у відповідь на ці події наведено нижче:

$(function() ( $("#draggable").draggable(); $("#droppable").droppable(( drop: function() ( $("#draggable").text("Залишено") )) , activate: function() ( $("#droppable").css(( border: "medium double green", backgroundColor: "lightGreen" )); ), deactivate: function() ( $("#droppable"). css("border", "").css("background-color", ""); ), over: function() ( $("#droppable").css(( border: "medium double red", backgroundColor : "red" )); ), out: function() ( $("#droppable").css("border", "").css("background-color", ""); ) )); ); Запустити приклад

Тут використані самі функції-обработчики, що у попередньому прикладі, але у разі вони пов'язані з подіями over і out. Коли з приймаючим елементом перекривається принаймні 50% елемента, що переміщається, він полягає в рамку і колір його фону змінюється, як показано на малюнку:

Вказана 50%-на межа називається порогом перекривання (tolerance), величину якого можна задавати при створенні приймаючого елемента, як буде показано далі.

Налагодження взаємодії Droppable

Для взаємодії Droppable передбачено низку властивостей, шляхом зміни яких можна налаштувати його поведінку. Ці властивості перелічені у таблиці нижче:

Властивості взаємодії Droppable Властивість Опис
disabled Якщо ця опція дорівнює true, функціональність взаємодії Droppable спочатку відключена. Значення за промовчанням - false
accept Звужує безліч елементів, що переміщаються, на які буде реагувати приймаючий елемент. Значення за промовчанням - *, йому відповідає будь-який елемент
activeClass Визначає клас, який присвоюватиметься у відповідь на подію activate та видалятиметься у відповідь на подію deactivate
hoverClass Визначає клас, який присвоюватиметься у відповідь на подію over та видалятиметься у відповідь на подію out
tolerance Визначає мінімальний ступінь перекривання, за якого відбувається подія over
Обмеження допустимих елементів, що переміщуються

Можна обмежити безліч елементів, що переміщуються, які будуть прийматися елементом, наділеним функціональністю взаємодії Droppable, за допомогою опції accept. Як значення опції accept слід присвоїти селектор. В результаті цієї події взаємодії Droppable відбуватимуться лише в тому випадку, якщо елемент, що переміщається, відповідає зазначеному селектору. Відповідний приклад наведено нижче:

... .draggable, #droppable (font-size: large; border: thin solid black; padding: 10px; width: 100px; text-align: center; background-color: lightgray; margin: 4px;) : 20px; position: absolute; right: 5px;) $(function() ( $(".draggable").draggable(); $("#droppable")). ui.draggable.text("Залишено") ), activate: function() ( $("#droppable").css(( border: "medium double green", backgroundColor: "lightGreen" )); ), deactivate: function () ( $("#droppable").css("border", "").css("background-color", ""); ), accept: "#drag1" )); )); Залишити тут Елемент 1 Елемент 2 Запустити приклад

У цьому прикладі є два елементи, що переміщуються з ідентифікаторами drag1 і drag2. При створенні приймаючого елемента використовується опція accept, за допомогою якої ми вказуємо, що прийнятним елементом, що переміщається, буде тільки елемент drag1.

При перетягуванні елемента drag1 ви спостерігатимете той самий ефект, що й у попередніх прикладах. У відповідні моменти для елемента, що приймає, будуть запускатися події activate, deactivate, over і out. У той же час, якщо перетягувати елемент drag2, який не відповідає вказаному в параметрі accept селектору, ці події запускатися не будуть. Цей елемент можна вільно переміщати, але він не сприйматиме приймаючий елемент.

Зверніть увагу на зміну способу вибору прийнятного елемента, що переміщається, для якого слід викликати метод text(). Коли в документі був лише один елемент, що переміщається, для цього вистачало атрибута id:

Drop: function() ( $("#draggable").text("Залишено") ),

У даному прикладі є два елементи, що переміщуються, і вибір по атрибуту id не дасть бажаного результату, оскільки текст в цьому випадку буде завжди змінюватися в одному і тому ж елементі, що переміщається, незалежно від того, який з них є прийнятним для приймаючого елемента.

Вихід полягає в тому, щоб використовувати об'єкт ui, який jQuery UI надає як додатковий аргумент кожному обробнику подій. Властивість draggable об'єкта ui повертає об'єкт jQuery, що містить елемент, який користувач перетягує або намагається залишити на цільовому елементі, що дозволяє вибрати потрібний елемент таким чином:

Drop: function(event, ui) (ui.draggable.text("Залишено")),

Зміна порога перекривання

За умовчанням подія over відбувається лише в тих випадках, коли принаймні 50% елемента, що переміщається, перекривається з приймаючим елементом. Величину цього порогового перекриття можна змінити за допомогою опції tolerance, яка може набувати значень, зазначених у таблиці нижче:

Найчастіше я використовую два значення, fit і touch, оскільки їхній зміст найбільш зрозумілий для користувачів. Значення fit використовується мною в тих випадках, коли елемент, що перетягується, повинен залишитися в тій області приймаючого елемента, в яку він був переміщений, а значення touch - коли переміщений елемент повинен повернутися у вихідну позицію (відповідний приклад буде наведено далі). Приклад використання параметрів fit та touch наведено нижче:

Значення clone вказує jQuery UI на те, що необхідно створити копію елемента, що переміщається разом з усім його вмістом і використовувати отриманий результат як допоміжний елемент. Результат представлений малюнку:

Допоміжний елемент видаляється, коли користувач відпускає кнопку миші над елементом, що переміщається, залишаючи переміщається і приймає елементи в їх вихідних позиціях.

Як показано на малюнку, вихідний елемент, що переміщається, залишається на своєму місці і лише допоміжний елемент переміщається по екрану слідом за покажчиком миші. Якщо розміри переміщуваного елемента великі, як і прикладі, він закриває собою інші елементи документа, отже навіть відстежити позицію приймаючого елемента користувачеві буде важко. З цією проблемою можна впоратися, надавши функцію як значення опції helper, як показано в прикладі нижче:

... $(function() ( $("div.draggable")..png"/>") ) )); $("#basket").droppable(( activeClass: "active", hoverClass: "hover" )); )); ... Запустити приклад

Коли користувач починає перетягувати елемент, jQuery UI викликає функцію, задану параметром helper, і використовує елемент, що повертається як об'єкт, що переміщається. В даному випадку я використовую jQuery для створення елемента img. Результат представлений малюнку:

Невелике зображення відіграє роль заступника елемента, що переміщується, що значно спрощує відстеження інших елементів документа.

Об'єкт ui, який jQuery UI передає подіям взаємодії Droppable, містить властивість helper, і цю властивість можна використовувати для маніпуляцій допоміжним елементом у процесі його перетягування. Приклад використання цієї властивості у зв'язці з подіями over та out наведено нижче:

... $(function() ( $("div.draggable")..png"/>") ) )); $("#basket").droppable(( activeClass: "active", hoverClass: "hover", over: function(event, ui) ( ui.helper.css("border", "thick solid #27e6ed") ) , out: function(event, ui) (ui.helper.css("border", ""))))); )); ...

Тут події over і out, а також властивість ui.helper використовуються для відображення рамки навколо допоміжного елемента, коли він перекриває елемент, що приймає. Результат представлений малюнку:

Прив'язка до країв елементів

За допомогою опції snap можна домогтися того, щоб елемент, що переміщається, як би "притягувався" до країв елементів, поряд з якими він проходить. Як значення ця опція набирає селектор. Елемент, що переміщається, буде прив'язуватися до країв будь-якого елемента, відповідного зазначеному селектору. Приклад використання опції snap наведено нижче:

Запустити приклад jQuery UI #snapper, .draggable, .droppable (font-size: large; border: medium solid black; padding: 4px; width: 150px; text-align: center; background-color: lightgray; margin-bottom: 10px ;) .droppable (margin-right: 5px; height: 50px; width: 120px) #dropContainer (position: absolute; right: 5px;) div span (position: relative; top: 25%) .droppable.active (border: medium solid green) .droppable.hover (background-color: lightgreen) #snapper (position: absolute; left: 35%; border: medium solid black; width: 180px; height: 50px) $(function() ( $(" div.draggable").draggable(( snap: "#snapper, .droppable", snapMode: "both", snapTolerance: 50 )); $("#basket").droppable(( activeClass: "active", hoverClass: "hover"));)); Кошик Прив'яжися тут Перетягни мене

Коли елемент, що переміщається, наближається до одного з відповідних елементів, він як би "притягується" до нього таким чином, що їх сусідні краї стикаються. Для такої прив'язки можна вибрати будь-який елемент, а не лише приймаючий. У цьому прикладі я додав елемент div і визначив для опції snap значення, яке вибирає в документі даний елемент, а також елемент, що приймає.

Існує пара допоміжних опцій, що дозволяють точніше налаштувати поведінку елементів щодо прив'язки. Одна з них - це опція snapMode. За її допомогою можна вказати тип прив'язки. Допускаються такі значення: inner(Прив'язка до внутрішніх країв елементів), outer(прив'язка до зовнішніх країв елементів) та both(Прив'язка до всіх країв; використовується за умовчанням).

Опція snapTolerance дозволяє вказати, на яку відстань повинен наблизитися елемент, що переміщається, до краю елемента-мішені, перш ніж відбудеться прив'язка. Значення за замовчуванням – 20, що означає 20 пікселів. У прикладі використовується значення 50 якому відповідає прив'язка на більшій відстані. Дуже важливо правильно вибрати значення цієї опції. Якщо значення опції snapTolerance занадто мало, то користувач може не помітити ефекту прив'язки, а якщо воно занадто велике, то елемент, що переміщається, почне робити несподівані стрибки, прив'язуючись до далеко розташованих елементів.

Використання технології перетягування(drag and drop ) дозволяє користувачеві переміщати різні об'єкти з одного в інший, наприклад, елементи одного списку в інший. Для цього необхідно використовувати два елементи керування: приймач та джерело. Приймачем вважається той об'єкт, який прийме об'єкт джерело (об'єкт, що переміщається).

Події, що виникають у процесі переміщення об'єктів, перераховані нижче в тому порядку, в якому вони виникають.

OnStartDrag(Тип TStartDragEvent) - на початку виконання операції генерується об'єктом-джерелом. Параметри, що передаються обробнику подій: об'єкт приймач DragObject (тип TDragObject), об'єкт-джерело Source (тип TObject).

OnDragOver(Тип TDragOverEvent) - створює об'єкт-приймач, коли над ним виявляється об'єкт, що переміщається. Параметри, які передаються обробнику подій: об'єкт-приймач Sender (тип TObject), об'єкт-джерело Source (тип TObject), стан переміщення State (тип TDragState), X та Y (тип integer) - поточні координати вказівника миші, Accept (тип boolean ) ознака підтвердження операції переміщення. Стан переміщення дає зрозуміти чи перебувати об'єкт в області приймача, чи пересувається в ній, покинув її. Передані параметри дозволяють об'єкту-приймачу прийняти або відхилити об'єкт-джерело. Параметр Accept встановлюється значення Trye якщо операцію переміщення прийнято, інакше - False.

onDragDrop (тип TDragDropEvent) - створюється об'єктом-приймачем, коли об'єкт, що переміщається, опускається на ньому. Оброблювачі події передаються поточні координати вказівника миші, об'єкт приймача Sender (тип TObject), вихідний об'єкт переміщення Source (тип TObject).

onEndDrag (тип EndDragEvent) - створюється при завершенні операції перетягування. Передаються обробнику події координати X і Y точки, де опинився об'єкт-джерело Sender та об'єкт приймач Target.

Для створення перетягування достатньо реалізувати дві події: OnDragDrop і OnDragOver при встановленій властивості DragMode, що дорівнює dmAutomatic. В іншому випадку початок операції переміщення, метод BeginDrag, необхідно програмісту закодувати.

Для закріплення матеріалу створимо наступну програму. На форму помістимо компонент Panel. У якості DragMode Інспектора Об'єктів встановимо значення dmAutomatic. Виділимо об'єкт форма і за допомогою Інспектора Об'єктів створимо наступні події:

Procedure TForm1.FormDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin if Source = Panel1 then Accept:= True else Accept:= False; end; procedure TForm1.FormDragDrop(Sender, Source: TObject; X, Y: Integer); begin Panel1.Left:= X; Panel1.Top:= Y; end;

Тепер запустивши програму та натиснувши над панеллю кнопку миші, ми можемо переміщати об'єкт панель по всій формі.

Підсумок: ми познайомилися з технологією перетягування(drag and drop) та використовували її на практиці.

Методи роботи з технікою "перетягни та кинь" складалися протягом багатьох років. Не дивно, що зі збільшенням числа програмістів, які розробляють плагіни з відкритим вихідним кодом (наприклад, для jQuery), знову відроджуються старі методи. Бібліотека для JavaScript вельми адаптивна і пропонує безліч покращень у наш час веб технологій.

У цьому уроці ми зробимо скрипт, який можна буде використовувати для створення динамічних прямокутників з технікою "перетягни та кинь" на своєму веб-сайті. Процес керується jQuery. Такі скрипти зберігають час, надаючи готовий функціонал! А бібліотеку "перетягни та кинь" можна буде використовувати в інших проектах.

Готуємо контент

Насамперед підготуємо невеликий сайт для проекту. У папці проекту потрібно створити два каталоги з примітними іменами "js" та "css" та порожній файл index.html. Код буде дуже простий, щоб склалося чітке уявлення про роботу і з'явилася точка для подальшого розвитку.

Нижче наводиться код нашого HTML-файлу. В розділі headми включаємо 3 скрипти. Основний скрипт jQuery підвантажуватиметься з сервера Google Code. також підключається наш файл стилів style.css, який містить основні властивості формування зовнішнього виглядунашого документа.

Перетягни мене Да-да. Саме мене. Мене також можна перетягнути ( zIndex: 200, opacity: .9 )

PS: мене можна кинути де завгодно!

Усередині розділу bodyвміщено лише два блоки div, які містять обидва прямокутники. Код досить простий та зрозумілий. Всередині кожного прямокутника розміщені заголовки з класами handler та handler2 . Це важливо, тому що при перетягуванні кожен прямокутник поводиться по-своєму.


Встановлюємо CSS

Код HTML дуже простий. Якщо вам зрозуміла основна розмітка, то і стилі CSS також не будуть складними. В основному визначаються поля, відступи та кольори.

Body,html ( font-family:Calibri, sans-serif; background:#eaf3fb; font-size:12px; height:1000px; line-height:18px; ) p ( height:30px; )

Селектори body,htmlвикористовуються лише для демонстраційної сторінки. А весь контент розміщується у двох прямокутниках, що перетягуються.

Dv1 ( width:200px; background-color:#eff7ff; border:1px solid #96c2f1; position:absolute; left:100px; top:100px; ) .dv1 h2 ( background-color:#b2d3f5; padding:5p family:Georgia, "Times New Roman", Times, serif; font-size:1.0em; text-transform:uppercase; font-weight:bold; ( padding:5px; margin-bottom:10px; ) .dv2 ( background-color:#f6ebfb; border:1px solid #a36fde; width:550px; position:absolute; cursor:move; left:400px; top:230px .dv2 h2 ( background-color:#eacfe9; letter-spacing:-0.09em; font-size:1.8em; font-weight: bold; padding:15px; margin:1px; color:#241f24; cursor:move; ) .dv2 .content2 ( padding:5px; margin-bottom:10px; )

Для обох класів.dv1 та.dv2 ми використовуємо абсолютне позиціонування. У цьому немає потреби і, ймовірно, це не самий кращий спосібдля позиціонування прямокутників, що перетягуються. Однак для нашого прикладу таке позиціонування має сенс, тому що при кожному оновленні сторінки прямокутники встановлюються у певні місця.

Також шрифти і кольори відрізняються прямокутників, щоб легше було побачити різницю.

В іншому заголовки та зміст блоків майже ідентичний. Якщо ви копіюватимете стилі у свій проект, поміняйте імена перед запуском. У деяких випадках логічніше використовувати ID замість класів, наприклад при використанні техніки "перетягни і кинь" для одного певного блоку.

Розбираємо JavaScript

Два файли JavaScript містять весь необхідний для роботи код. Опустимо деталі роботи з jQuery, оскільки це виходить за межі уроку. Звернімо увагу на файл jquery.dragndrop.js.

На рядку 22 відбувається визначення функції Drags.

$.fn.Drags = function(opts) ( var ps = $.extend(( zIndex: 20, opacity: .7, handler: null, onMove: function() ( ), onDrop: function() ( ) ), opts );

Тут встановлюється повертається змінна та дані ініціалізації для Drags. Такий спосіб дуже широко використовується під час роботи з jQuery для передачі опцій іншим функціям. Усередині ми встановлюємо змінні для всіх доступних опцій для прямокутників, що перетягуються.


Наступна частина коду включає обробники подій для змінної dragndrop. Обидві події dragі dropвикликають функції з передачею параметрів події у них. Ці події відбуваються, коли ви натискаєте кнопку миші, щоб перетягнути об'єкт, а потім відпускаєте її.

Var dragndrop = ( drag: function(e) ( var dragData = e.data.dragData; dragData.target.css(( left: dragData.left + e.pageX - dragData.offLeft, top: dragData.top + e.pageY - dragData.offTop )); dragData.handler.css(( cursor: "move" )); dragData.target.css (( cursor: "move" )); dragData.onMove(e); ), drop: function( e) ( var dragData = e.data.dragData; dragData.target.css(dragData.oldCss); //.css(( "opacity": "" )); dragData.handler.css("cursor", dragData). oldCss.cursor), dragData.onDrop(e); $().unbind("mousemove", dragndrop.drag) .unbind("mouseup", dragndrop.drop);

Наші функції маніпулюють CSS позиціонуванням кожного об'єкта. Якщо змінити абсолютне позиціонування ваших об'єктів, це не вплине на роботу коду, тому що кожна функція JavaScript змінює будь-який стиль, визначений для об'єкта.

В іншому коді відбувається перевірка оброблювача та косметичні зміни інших стилів. Тут можна додати зміну прозорості, шрифту та його кольору або додати нові параграфи.

Функції Drag/Drop

У другому файлі fn.js міститься дуже простий код. Ми чекаємо повного завантаженнядокумента, після чого викликаємо наші функції. Визначаються два екземпляри функції Drags, яка розбиралася раніше.

У нас є два блоки, що переміщаються з класами.dv1 і.dv2 . Якщо потрібно залишити один блок, що переміщається, то потрібно просто видалити другу частину коду. Додавання ще одного блоку, що переміщається, також здійснюється просто. Потрібно лише додати нову функцію у цьому файлі.

Насамперед потрібно встановити опції при виклику функції. Обов'язково необхідно встановити ім'я оброблювача. З його допомогою ми повідомляємо jQuery, який обробник використовувати при натисканні кнопки миші у певній області документа. Як ім'я обробника може бути клас або атрибут ID.

У нашій першій функції є два обробники подій onMove і onDrop. Обидва викликають нові функції, що передаються у поточну подію як змінні. Тут виконується маніпулювання HTML-кодом у прямокутнику для оновлення при кожному русі. Це чудовий ефект для демонстрації того, як можна керувати процесом за допомогою простих подій jQuery.

У другій функції ми використовуємо параметри z-Index та opacity. Чи можна додати інші властивості CSS? але для цього потрібно переробити код JavaScript, щоб здійснювати перевірку установок. Наприклад, можна передавати інший стиль шрифту або значення для висоти і ширини для прямокутника, що переміщується - вийде дуже цікавий трюк!

Висновок

В результаті невеликої роботи ми отримали у своє розпорядження чудовий інтерфейс з функцією "перетягни та кинь". jQuery надає величезні переваги для розробників, які прагнуть використати у своїх проектах старі методи.

В результаті ми отримали не тільки функції обробники подій, але й можемо передавати нові змінні в блоки, що перетягуються. Це відкриває нові змогу творчості. Демонстрація до уроку містить лише малюнок те, що можна робити з допомогою такого коду.

Отже, вивчайте документацію jQuery для використання бібліотечних функцій.

Для бібліотеки VCL фірмою Borland реалізовано власну версію інтерфейсу Drag&Drop (перекладається як "перетягнути"). Інтерфейс цей внутрішній - передавати і приймати можна будь-які керуючі елементи Delphi всередині форми (крім самої форми). Він реалізований без використання відповідних функцій API Windows - їх потрібно застосовувати при організації спілкування з іншими завданнями шляхом перетягування.

Натиснувши ліву кнопку миші над елементом управління, ми можемо "перетягнути" його будь-який інший елемент. З точки зору програміста це означає, що в моменти перетягування і відпускання клавіші генеруються певні події, якими передається вся необхідна інформація - покажчик на об'єкт, що перетягується, поточні координати курсора та ін. Одержувачем подій є той елемент, на якому в даний момент знаходиться курсор. Обробник такої події повинен повідомити систему, чи приймає даний елемент управління "посилання" чи ні. При відпусканні кнопки над елементом управління, що приймає, генерується ще одна або дві події, в залежності від готовності приймача.

CancelDrag Скасує поточну операцію drag-and-drop або drag-and-dock.

Функція FindDragTarget (const Pos: TPoint; AllowDisabled: Boolean): TControl;

Функція повертає об'єкт базового класу TControl , якого відноситься позиція екрана з координатами, визначеними параметром Pos. Ця функція використовується для визначення потенційного одержувача drag-and-drop або drag-and-dock операції. Якщо вказаної позиції немає ніякого віконного засобу управління, то функція повертає nil . Параметр AllowDisabled визначає, чи враховуватимуться заблоковані (disabled) об'єкти.

Функція IsDragObject (Sender: TObject): Boolean;

Функція визначає, чи об'єкт, визначений у параметрі Sender, нащадком класу TDragObject . Цю функцію можна використовувати як параметр Source в обробниках подій OnDragOver і OnDockOver для того, щоб визначити, чи буде прийнятий об'єкт, що перетягується. Також функцію IsDragObject можна використовувати як параметр Source в обробниках подій OnDragDrop і OnDockDrop для того, щоб правильно інтерпретувати об'єкт, що перетягується.

Властивості DragMode, DragCursor, методи BeginDrag, OnDragOver, OnDragDrop, OnEndDrag, OnStartDrag, параметр Accept

Процес перетягування за допомогою миші інформації з одного об'єкта в інший широко використовується в Widows. Можна переміщувати файли між папками, переміщати самі папки та ін.

Всі властивості, методи та події, пов'язані з процесом перетягування, визначені в класі TControl, що є прабатьком всіх візуальних компонентів Delphi. Тому вони є спільними всім компонентів.

Початок перетягування визначається властивістю DragMode, яка може встановлюватися в процесі проектування або програмно рівним dmManual або dmAutomatic. Значення dmAutomatic (автоматичне) визначає автоматичний початок процесу перетягування при натисканні кнопки миші над компонентом. Проте в цьому випадку подія OnMouseDown, пов'язана з натисканням кнопки миші, для цього компонента взагалі не настає.

Інтерфейс перенесення та прийому компонентів з'явився досить давно. Він забезпечує взаємодію двох елементів керування під час виконання програми. При цьому можуть виконуватись будь-які необхідні операції. Незважаючи на простоту реалізації та давність розробки, багато програмістів (особливо новачків) вважають цей механізм малозрозумілим та екзотичним. Проте використання Drag-and-Drop може виявитися дуже корисним та простим у реалізації. Зараз ми переконаємося в цьому.

Для того, щоб механізм запрацював, потрібно налаштувати відповідним чином два елементи управління. Один має бути джерелом (Source), другий – приймачем (Target). При цьому джерело нікуди не переміщається, а тільки реєструється як таке в механізмі.

Повірте, досить просто перетворити X,Y координати, що передаються в параметрах подій OnDragOver і OnDragDrop, координати форми.

Працюйте з властивостями Left та Top компонента, над яким переміщується курсор. Наведу найпростіший приклад. Помістіть на форму компонент Memo і надайте властивості Align значення alTop. Помістіть на форму панель, також привласніть Align значення alTop і задайте невелике значення властивості Height, скажімо 6 або 7 пікселів. Встановіть DragMode на dmAutomatica та DragCursor на crVSplit. Помістіть інший Memo-компонент та встановіть Align на alClient. Одночасно виберіть обидва компоненти Memo, панель і створіть спільний обробник події OnDragOver як показано нижче:

Нещодавно у мене з'явилася ідея зайнятися розробкою гри для андроїд. Спочатку я вирішив написати шахи. Мені здавалося технологія Drag and Drop відмінно підійде для реалізації механізму переміщення фігур. Для непосвячених зазначу, що метод drag and drop полягає у можливості перетягування одних графічних об'єктів на інші та виконання тієї чи іншої дії після відпускання. Найпростіший приклад – видалення ярлика з робочого столу вашого ПК перетягуванням його в кошик. "Кинувши" ярлик у кошик, ми говоримо системі, що хочемо змусити взаємодіяти ці два об'єкти. Система отримує наш сигнал і вирішує, яку дію їй варто зробити. Drag and drop набула широкого поширення завдяки своїй інтуїтивній ясності. Цей підхід підкріплений нашим досвідом взаємодії з об'єктами реального світу та чудово працює у віртуальному середовищі. Що ж до шахів, за допомогою drag and drop технологічно простіше визначити клітину, куди користувач перетягнув фігуру, оскільки не потрібно обчислювати номер клітини за координатами точки відпускання. Цю роботу візьме він віртуальна машина.

Цілі використання технології Drag n Drop

Використання технології drag and drop дозволяє мені малою кров'ю вирішити три завдання:

  • Візуалізація ходу. Коли користувач стосується фігури і починає її переміщення екраном, фігура замінюється дрібнішим малюнком. Таким чином, користувач розуміє, що фігура захоплена.
  • Я обмежив область руху фігури розмірами дошки.
  • Якщо користувач відпустив фігуру в неправильному місці, вона має повернутися до початкового положення.
  • Завдання позначені, приступимо до їх реалізації.

    Підміна ImageView під час торкання

    Усі мої фігури є об'єктами ImageView. На жаль, виявилося, що реалізація Drag & Drop в Android не дозволяє "прямо з коробки" здійснювати заміну зображення об'єкта при його торканні. Тим не менш, це завдання цілком вирішуване засобами API. Нам знадобиться виконати низку нескладних дій:

  • Створити об'єкт DragShadowBuilder.
  • Викликати метод startDrag.
  • Сховати наш ImageView, який відображає фігуру, викликавши метод setVisibility з параметром View.INVISIBLE. В результаті на екрані залишиться лише об'єкт DragShadowBuilder, що буде сигналом для користувача про захоплення фігури.
  • Ці дії необхідно реалізувати в обробнику OnTouchListner об'єкту ImageView. Для цього перевизначимо метод onTouch:

    @ Override public boolean onTouch(View view, MotionEvent motionEvent) ( if (motionEvent. getAction() == MotionEvent. ACTION_DOWN) ( ClipData clipData= ClipData. newPlainText("" , "" ) ; View. DragShadowBuilder dsb= new View (view) ;view.startDrag(clipData, dsb, view, 0 ) ;view.setVisibility(View. INVISIBLE) ; return true ;

    Все дуже просто. Отже, із заміною зображення розібралися, перейдемо до наступного завдання.

    Обмеження області перетягування для функції drag drop

    Обмеження області перетягування пов'язані з однією проблемою. Справа в тому, що якщо відпустити фігуру за межами дошки, події drop не трапиться, оскільки користувач відпустив об'єкт на порожньому місці, і об'єкту нема з чим взаємодіяти. В результаті постать не повернеться у свій первісний стан і так і залишиться назавжди захованою. Я вбив багато часу на читання документації, але так і не знайшов способу обмежити область перетягування об'єктів. Осяяння прийшло раптово. Мені зовсім не потрібно обмежувати область, мені потрібно дізнатися, чи правильно користувач відпустив фігуру чи ні.

    Визначення правильності відпускання
    Відповіді на свої запитання я знайшов у розділі handling drag end events на сайті Android Developers. Ось кілька ключових моментів:

  • Коли користувач завершує перетягування в обробнику DragListeners, генерується подія ACTION_DRAG_ENDED.
  • У DragListener можна отримати докладнішу інформацію про операцію drag, викликавши метод DragEvent.getResult().
  • Якщо DragListener повертає true у відповідь на подію ACTION_DROP, виклик getResult також поверне true, інакше - false.
  • Таким чином, мені потрібно перехопити подію ACTION_DRAG_ENDED та викликати метод getResult. Якщо він поверне false, то користувач потягнув фігуру за межі дошки, і мені потрібно перевести ImageView у видимий режим.

    @ Override public boolean onDrag(View view, DragEvent dragEvent) ( int dragAction= dragEvent. getAction() ; View dragView= (View) dragEvent. getLocalState() ; if (dragAction== DragEvent. ACTION_DRAG_EXITED) ( containsDragable= if (dragAction== DragEvent. ACTION_DRAG_ENTERED) ( containsDragable= true ; ) else if (dragAction== DragEvent. ACTION_DRAG_ENDED) ( if (dropEventNotHandled(dragEvent) ) ( dragView. setVisibility(View. VISIBLE) = DragEvent.ACTION_DROP&&containsDragable) ( checkForValidMove((ChessBoardSquareLayoutView) view, dragView) ; dragView. setVisibility(View. VISIBLE) ; ) return true ; Result( ) ; )

    Тепер користувач може будь-де відпускати фігуру, і нічого страшного не станеться.

    Визначення допустимих ходів

    Остання частина статті присвячена перевірці допустимості ходу, яку намагається зробити користувач. Перш ніж докладно розпочати обговорення цієї теми, зроблю невелику ремарку, яка пояснює структуру мого додатка. Шахова дошка представлена ​​як TableLayout, а кожна клітина є нащадком LinearLayout і має OnDragListener.

    Крім того, кожен OnDragListener посилається на об'єкт "посередника" (mediator), який піклується про взаємодію ігрових об'єктів та запам'ятовує положення поточної клітини.

    Коли користувач тягне фігуру над клітиною, можливі такі дії:

  • Використання події ACTION_DRAG_ENTERED для встановлення змінної 'containsDraggable' у true.
  • Використання події ACTION_DRAG_EXITED для встановлення змінної 'containsDraggable' у false.
  • Використання події ACTION_DROP для запиту посередника про допустимість встановлення фігури цієї клітини.
  • Нижче наведено код, який реалізує описану логіку

    @ Override public boolean onDrag(View view, DragEvent dragEvent) ( int dragAction= dragEvent. getAction() ; View dragView= (View) dragEvent. getLocalState() ; if (dragAction== DragEvent. ACTION_DRAG_EXITED) ( containsDragable= if (dragAction== DragEvent. ACTION_DRAG_ENTERED) ( containsDragable= true ; ) else if (dragAction== DragEvent. ACTION_DRAG_ENDED) ( if (dropEventNotHandled(dragEvent) ) ( dragView. setVisibility(View. VISIBLE) = DragEvent.

    Як бачите, незалежно від того чи допустимий хід чи ні, ImageView переводиться у видимий стан. Я хотів, щоб користувач бачив, як рухається фігура. Раніше я згадував, що клітина є нащадком LayoutView. Це зроблено для того, щоб простіше переміщати ImageView від клітини до клітини. Нижче наводиться код методу checkForValidMove, який показує, як відбувається переміщення ImageView.

    private void checkForValidMove(ChessBoardSquareLayoutView view, View dragView) ( if (mediator. isValidMove(view) ) ( ViewGroup owner = (ViewGroup) dragView. (Gravity. CENTER) ; view. showAsLanded() ; mediator. handleMove(view) ; ) )

    Сподіваюся, ця стаття допоможе Вам під час розробки власних проектів.

    
    Top