Часть 12: Drag & Drop
Что такое drag & drop?
& drop ("перетащил и
оставил"). Для этого Вам понадобится по крайней мере Netscape Navigator 4.0,
поскольку мы будем пользоваться особенностями языка JavaScript 1.2.
Что такое drag & drop? Например, некоторые операционные системы (такие как
Win95/NT или MacOS) позволяют Вам стирать файлы, просто перетаскивая их в
мусорную карзину. Иными словами, Вы щелкаете клавишей мыши над изображением
файла, перетаскиваете его (то есть держите клавишу нажатой и просто двигаете
мышь) - drag - в мусорную карзину, а затем отпускаете - drop - его там.
Механизм drag & drop, который мы хотим здесь реализовать, ограничивается web-
страницей. Поэтому Вы не можете использовать представленный здесь код, чтобы
переносить объекты с HTML-страницы на жесткий диск вашего компьютера или другие
подобные действия. (Начиная с версии 4.0 браузера Netscape Navigator ваш скрипт
может реагировать на событие с названием DragDrop, событие, когда кто-либо
перетаскивает файл на окно вашего браузера. Но это не совсем то, о чем мы здесь
хотим поговорить)
(Онлайновая версия руководства позволяет Вам незамедлительно проверить пример,
описанный в этом уроке. В окне видны три кубика, которые можно передвигать с
помощью мыши)
Также можно рассмотреть пример, предоставленный компанией Netscape. Найти его
Вы сможете по адресу:
http://home.netscape.com/comprod/products/communicator/user_agent_vacation.html
& drop. Это значит, что
у нас нет возможности назначить объекту image свойство dragable (перемещаемый)
или что-либо в этом роде. Поэтому мы должны сами писать необходимый для этого
код. Впрочем, Вы увидите, что это не так сложно.
Итак, то же нам нужно? Нам нужны две вещи. Во-вервых, мы должны регистрировать
определенные события, связанные с работой мышью, то есть нужно понять, каким
образом, мы сможем узнать, какой объект необходимо переместить и на какую
позицию? Затем нам нужно подумать, каким именно образом мы сможем показывать
перемещение объектов по экрану. Конечно же, мы будем пользоваться такой новой
возможностью языка, как слои, при создании объектов и перемещении их по
экрану. Каждый объект представлен собственным слоем.
События при работе с мышью в JavaScript 1.2
Какие события, происходящие при работе с мышью, нам следует использовать? У нас
нет такого события, как MouseDrag, однако того же самого мы можем достичь,
отслеживая события MouseDown, MouseMove и MouseUp. В версии 1.2 языка
JavaScript используется новая модель событий. И без нее мы не смогли бы решить
нашу задачу. Я уже говорил об этой новой модели на предыдущем уроке. Однако
давайте взглянем на некоторые важные ее части еще раз.
Пользователь нажал клавишу мыши в каком-либо месте на окне браузера. Наш скрипт
должен зафиксировать это событие и вычислить, с каким объектом (то есть слоем)
это было связано. Нам необходимо знать координаты точки, где произошло это
событие. В JavaScript 1.2 реализован новый объект Event, который сохраняет
координаты этой точки (а также еще и другую информацию о событии).
Другой важной момент заключается в перехвате событий. Если пользователь,
например, щелкает по клавише мыши, то сигнал о соответствующем событии
посылается непосредственно объекту button. Однако в нашем примере необходимо,
чтобы событие обрабатывалось объектом window (окно). Поэтому мы позволяем
объекту окна перехватывать сигнал о событии, связанном с мышью, т.е. чтобы
именно объект window фиксировал это событие и имел возможность на него
реагировать. Это демонстрируется в следующем примере (на примере события
Click). Вы можете щелкнуть в любом месте окна браузера. При этом возникнет окно
сообщения, где будут показаны координаты точки, где это событие имело место.
Код этого примера:
<html>
<script language="JavaScript">
<!--
window.captureEvents(Event.CLICK);
window.onclick= displayCoords;
function displayCoords(e) {
alert("x: " + e.pageX + " y: " + e.pageY);
}
// -->
</script>
Щелкните клавишей мыши где-нибудь в окне браузера.
</html>
Сперва мы сообщаем, что объект window перехватывает сигнал о событии Click. Для
этого мы пользуемся методом captureEvent(). Строка
window.onclick= displayCoords;
что Вам при этом нельзя
ставить скобки после слова displayCoords). В свою очередь, displayCoords() -
это функция, которая определяется следующим образом:
function displayCoords(e) {
alert("x: " + e.pageX + " y: " + e.pageY);
}
Как видите, эта функция имеет аргумент (мы назвали его e). На самом деле это
объект Event, который передается на обработку функции displayCoords(). Объект
Event имеет свойства pageX и pageY (наряду с другими), из которых моно получить
координаты точки, где произошло событие. Окно с сообщением лишь показывает эти
значения.
MouseDown, MouseMove и MouseUp
Как я уже говорил, в языке JavaScript нет события MouseDrag. Поэтому мы должны
пользоваться событиями MouseDown, MouseMove и MouseUp, реализуя механизм drag &
drop. В следующем примере демонстрируется применение MouseMove - текущие
координаты курсора мыши отображаются в окне состояния.
Можно видеть, что код скрипта почти такой же, как и в предыдущем примере:
<html>
<script language="JavaScript">
<!--
window.captureEvents(Event.MOUSEMOVE);
window.onmousemove= displayCoords;
function displayCoords(e) {
status= "x: " + e.pageX + " y: " + e.pageY;
}
// -->
</script>
Координаты мыши показаны в строке состояния.
</html>
событие MouseMove, Вы
должны писать ее строчными буквами: window.onmousemove=...
Теперь мы можем объединить оба последних примера. Мы хотим, чтобы были
представлены координаты указателя мыши, когда пользователь перемещает мышь,
нажав на клавишу.
Код этого примера выглядит следующим образом:
<html>
<script language="JavaScript">
<!--
window.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP);
window.onmousedown= startDrag;
window.onmouseup= endDrag;
window.onmousemove= moveIt;
function startDrag(e) {
window.captureEvents(Event.MOUSEMOVE);
}
function moveIt(e) {
// показывать координаты
status= "x: " + e.pageX + " y: " + e.pageY;
}
function endDrag(e) {
window.releaseEvents(Event.MOUSEMOVE);
}
// -->
</script>
Двигайте мышь, удерживая ее клавишу нажатой. В окне состояния при этом
отображаются координаты курсора.
</html>
Во-первых, мы заставляем объект window перехватывать сигналы о событиях
MouseDown and MouseUp:
window.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP);
события имеют место:
window.onmousedown= startDrag;
window.onmouseup= endDrag;
В следующей строке кода определяется, что происходит, когда объект window
получает сигнал о событии MouseMove.
window.onmousemove= moveIt;
moveIt(), раз сигнал об этом
событии никогда не достигает объекта window? Ответ на этот вопрос можно найти в
функции startDrag(), которая вызывается сразу после того, как произойдет
событие MouseDown:
function startDrag(e) {
window.captureEvents(Event.MOUSEMOVE);
}
Это означает, что объект window начнет перехватывать событие MouseMove, как
только будет нажата клавиша кнопка мыши. И мы должны прекратить перехватывать
событие MouseMove, если произойдет событие MouseUp. Это делается в функции
endDrag() с помощью метода releaseEvents():
function endDrag(e) {
window.releaseEvents(Event.MOUSEMOVE);
}
Функция moveIt() записывает координаты мыши в окно состояния.
Теперь у нс есть все элементы скрипта, необходимые для регистрации событий,
связанных с реализацией механизма drag & drop. И мы можем приступить к
рисованию на экране наших объектов.
Показ движущихся объектов
На предыдущих уроках мы видели, как с помощью слоев можно создать
перемещающиеся объекты. Все, что мы должны теперь сделать - это определить, по
какому именно слою пользователь щелкнул клавишей мыши. И затем этот объект
должен двигаться вслед за мышью. Итак, код примера, показанного в начале этого
урока:
<html>
<head>
<script language="JavaScript">
<!--
var dragObj= new Array();
var dx, dy;
window.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP);
window.onmousedown= startDrag;
window.onmouseup= endDrag;
window.onmousemove= moveIt;
function startDrag(e) {
currentObj= whichObj(e);
window.captureEvents(Event.MOUSEMOVE);
}
function moveIt(e) {
if (currentObj != null) {
dragObj[currentObj].left= e.pageX - dx;
dragObj[currentObj].top= e.pageY - dy;
}
}
function endDrag(e) {
currentObj= null;
window.releaseEvents(Event.MOUSEMOVE);
}
function init() {
// задать 'перемещаемые' слои
dragObj[0]= document.layers["layer0"];
dragObj[1]= document.layers["layer1"];
dragObj[2]= document.layers["layer2"];
}
function whichObj(e) {
// определить, по какому объекту был произведен щелчок
var hit= null;
for (var i= 0; i < dragObj.length; i++) {
if ((dragObj[i].left < e.pageX) &&
(dragObj[i].left + dragObj[i].clip.width > e.pageX) &&
(dragObj[i].top < e.pageY) &&
(dragObj[i].top + dragObj[i].clip.height > e.pageY)) {
hit= i;
dx= e.pageX- dragObj[i].left;
dy= e.pageY- dragObj[i].top;
break;
}
}
return hit;
}
// -->
</script>
</head>
<body onLoad="init()">
<layer name="layer0" left=100 top=200 clip="100,100" bgcolor="#0000ff">
<font size=+1>Object 0</font>
</layer>
<layer name="layer1" left=300 top=200 clip="100,100" bgcolor="#00ff00">
<font size=+1>Object 1</font>
</layer>
<layer name="layer2" left=500 top=200 clip="100,100" bgcolor="#ff0000">
<font size=+1>Object 2</font>
</layer>
</body>
</html>
Можно видеть, что в разделе <body> нашей HTML-страницы мы определяем три слоя.
После того, как была загружена вся страница, при помощи программы обработки
события onLoad, указанной в тэге <body>, вызывается функция init():
function init() {
// define the 'dragable' layers
dragObj[0]= document.layers["layer0"];
dragObj[1]= document.layers["layer1"];
dragObj[2]= document.layers["layer2"];
}
код, что использовался ранее для
перехвата событий, связанных с мышью:
window.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP);
window.onmousedown= startDrag;
window.onmouseup= endDrag;
window.onmousemove= moveIt;
К функции startDrag() я добавил следующую сроку:
currentObj= whichObj(e);
Функция whichObj() определяет, по какому объекту был произведен щелчок.
Возвращает она номер соответствующего слоя. Если ни один слой не был выделен,
то возвращается значение null. Полученное значение хранится в переменной
currentObj. Это означает, что из currentObj можно извлечь номер слоя, который в
данный момент необходимо перемещать (либо это будет null, если никакого слоя
перемещать не надо).
В функции whichObj()для каждого слоя мы проверяем свойства left, top, width и
height. По этим значеням мы и можем проверять, по которому из объектов
пользователь щелкнул клавишей.
"Оставляемые" объекты
Теперь мы имеем все, что необходимо, чтобы реализовать механизм drag & drop. С
помощью нашего скрипта пользователь может перемещать объекты по web-странице.
Однако мы еще ничего не говорили об размещении перемещенных объектов.
Предположим, Вы хотите создать онлайновый магазин. У нас есть несколько
изделий, которые можно поместить в корзину. Пользователь должен переносить эти
изделия в корзинку и оставлять их там. Это означает, что мы должны
регистрировать моменты, когда пользователь опускает некий объект в корзину -
иными словами, что он хочет купить его.
Какую часть кода мы должны изменить, чтобы сделать такое? Мы должны проверить,
в какой месте оказался объект после того, как было зафиксировано событие
MouseUp - то есть мы должны сделать некоторые добавления к функции
endDrag().Например мы могли бы проверять, попадает ли в этот момент курсор мыши
в границы некого прямоугольника. Если это так, то Вы вызываете функцию,
регистрирующую все изделия, которые необходимо купить (например, Вы можете
поместить их в некий массив). Ну и после этого Вы можете показывать это изделие
уже в корзинке.
Реализации
бы странным, если бы Вы перемещали
объект, а он при этом прятался от Вас за окружающие предметы. Очевидно, что эту
проблему можно решить, меняя лишь порядок следования слоев в функции
startDrag().
Я далек от мысли, что Вас устроит перемещение красных, зеленых и синих кубиков
по Вашей web странице. Добавьте немного красивой графики, и читатели уже
запомнят Вашу страницу. Вы можете поместить что-либо в объект слоя. Например,
положите туда один тэг <img>, если хотите, чтобы ваш объект предстал в виде
графического изображения.
[Назад] [Содержание]
| Главная |