JavaScript CSS修改学习第六章 拖拽


当示例的box上的#链接处于活动状态的时候(不论是用tab然后点击enter或者使用鼠标点击)这个元素就能够通过方向键拖拽。然后点击enter或者Esc释放。(可以随意改变这些键。我不确定释放键应该设置成为什么所以enter和Esc都可以)

使用

1、复制文章后面的dragDrop对象。

2、复制我的addEventSimple和removeEventSimple函数,这里需要。

3、设定keyHTML和keySpeed属性(下面有解释)。

4、确定你所要拖拽的元素都有位置属性:absolute或者fixed。

5、把所有可拖拽的元素发送到对象的initElement函数。可以发送一个对象或者对象ID的字符串。例如:

dragDrop.initElement('test');
dragDrop.initElement(document.getElementById('test2'));

6、当元素被拖拽过后,代码会自动添加dragged类。你可以添加一些CSS效果。

7、如果你想当用户放开元素之后做一些事情,你可以给releaseElement添加自己的函数。

属性

你需要设置两个属性。

keyHTML包含一个需要拖拽的元素的键盘能访问到的链接的内容。为了保持HTML简洁,这里只添加一个有简单样式的类。你可以随意构建你的HTML,但是要记住一点就是必须有一个链接让键盘能够访问到,键盘用户需要一个焦点来触发拖拽事件。

keySpeed用来设置键盘拖拽的速度,每次按键移动多少像素。我喜欢设置为10,你也可以尝试一下其他的值。

这里还有7个属性,但是都是在代码内部的。初始化的时候都设置为undefined,然后相应的函数会设置他们。

拖拽对象


复制下面这个对象到你的页面,不要忘了addEventSimple和removeEventSimple。

复制代码 代码如下:

dragDrop = {
keyHTML: '<a href="#" class="keyLink">#</a>',
keySpeed: 10, // pixels per keypress event
initialMouseX: undefined,
initialMouseY: undefined,
startX: undefined,
startY: undefined,
dXKeys: undefined,
dYKeys: undefined,
draggedObject: undefined,
initElement: function (element) {
if (typeof element == 'string')
element = document.getElementById(element);
element.onmousedown = dragDrop.startDragMouse;
element.innerHTML += dragDrop.keyHTML;
var links = element.getElementsByTagName('a');
var lastLink = links[links.length-1];
lastLink.relatedElement = element;
lastLink.onclick = dragDrop.startDragKeys;
},
startDragMouse: function (e) {
dragDrop.startDrag(this);
var evt = e || window.event;
dragDrop.initialMouseX = evt.clientX;
dragDrop.initialMouseY = evt.clientY;
addEventSimple(document,'mousemove',dragDrop.dragMouse);
addEventSimple(document,'mouseup',dragDrop.releaseElement);
return false;
},
startDragKeys: function () {
dragDrop.startDrag(this.relatedElement);
dragDrop.dXKeys = dragDrop.dYKeys = 0;
addEventSimple(document,'keydown',dragDrop.dragKeys);
addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
this.blur();
return false;
},
startDrag: function (obj) {
if (dragDrop.draggedObject)
dragDrop.releaseElement();
dragDrop.startX = obj.offsetLeft;
dragDrop.startY = obj.offsetTop;
dragDrop.draggedObject = obj;
obj.className += ' dragged';
},
dragMouse: function (e) {
var evt = e || window.event;
var dX = evt.clientX - dragDrop.initialMouseX;
var dY = evt.clientY - dragDrop.initialMouseY;
dragDrop.setPosition(dX,dY);
return false;
},
dragKeys: function(e) {
var evt = e || window.event;
var key = evt.keyCode;
switch (key) {
case 37: // left
case 63234:
dragDrop.dXKeys -= dragDrop.keySpeed;
break;
case 38: // up
case 63232:
dragDrop.dYKeys -= dragDrop.keySpeed;
break;
case 39: // right
case 63235:
dragDrop.dXKeys += dragDrop.keySpeed;
break;
case 40: // down
case 63233:
dragDrop.dYKeys += dragDrop.keySpeed;
break;
case 13: // enter
case 27: // escape
dragDrop.releaseElement();
return false;
default:
return true;
}
dragDrop.setPosition(dragDrop.dXKeys,dragDrop.dYKeys);
if (evt.preventDefault)
evt.preventDefault();
return false;
},
setPosition: function (dx,dy) {
dragDrop.draggedObject.style.left = dragDrop.startX + dx + 'px';
dragDrop.draggedObject.style.top = dragDrop.startY + dy + 'px';
},
switchKeyEvents: function () {
// for Opera and Safari 1.3
removeEventSimple(document,'keydown',dragDrop.dragKeys);
removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
addEventSimple(document,'keypress',dragDrop.dragKeys);
},
releaseElement: function() {
removeEventSimple(document,'mousemove',dragDrop.dragMouse);
removeEventSimple(document,'mouseup',dragDrop.releaseElement);
removeEventSimple(document,'keypress',dragDrop.dragKeys);
removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
removeEventSimple(document,'keydown',dragDrop.dragKeys);
dragDrop.draggedObject.className = dragDrop.draggedObject.className.replace(/dragged/,'');
dragDrop.draggedObject = null;
}
}

拖拽是什么
拖拽是在屏幕上移动元素的一种方法。为了让元素能够移动,元素必须有position属性:absolute或者fixed,这样才能通过修改它的坐标(style.top和style.left)让它移动。
(理论上position:relative也可以,但是几乎没用。另外,那样需要额外的数据来计算,这里我没有写)
设置坐标很简单;找到需要设置的元素的坐标是这个代码比较难的部分。大多数代码都是用来处理这个问题的。
另外,保持易用性也比较重要。传统上通过鼠标来拖拽一个元素是最好的办法,但是也要考虑到没有鼠标的用户,所以也要保证键盘的可用性。

基础知识
让我们先来看看一些基础知识
初始化一个元素
每个拖拽代码都从初始化元素开始。这个工作通过下面的函完成:
复制代码 代码如下:

initElement: function (element) {
if (typeof element == 'string')
element = document.getElementById(element);
element.onmousedown = dragDrop.startDragMouse;
element.innerHTML += dragDrop.keyHTML;
var links = element.getElementsByTagName('a');
var lastLink = links[links.length-1];
lastLink.relatedElement = element;
lastLink.onclick = dragDrop.startDragKeys;
},

如果函数接收到一个字符串,那么就会当做元素ID来处理。然后给这个元素设置一个onmousedown事件,用来开始鼠标部分的代码。注意这里我使用的是传统事件注册方式;因为我希望this关键字能够在startDragDrop里起作用。

然后把用户定义的keyHTML添加到元素上,我相信这个链接是用来触发键盘事件的。然后为这个链接设置键盘的触发程序。然后存储主元素在relatedElement里面,我们后面需要。

现在代码就等用户动作了

基本位置信息
我打算使用下面的方法来:首先我会读取拖拽元素的初始位置,保存在startX和startY里面。然后计算鼠标移动的位置或者键盘控制下移动的位置来决定元素从初始位置移动的范围。
在这里查找键盘代码。

case 13: // enter
case 27: // escape
dragDrop.releaseElement();
return false;

事件

点击可以激活元素。当鼠标点击链接或者当元素获得焦点的时候点击enter键就能激活。所以键盘代码的激活可以使点击enter键或者点击链接。

(严格来说,当你用鼠标点击链接的时候,元素先被鼠标事件激活然后释放了然后再被键盘模式激活。)

事件的其余部分也非常的模糊。当你想检测方向键的时候键盘事件尤为麻烦。

首先我们需要一个允许重复点击的事件,因为用户可能按着方向键不放,那么事件就需要一遍遍的触发,这样拖拽才能继续。所以我们使用keypress事件。

不幸的是,IE在keypress的情况下不支持方向键。在IE里面keydown会重复发生,看起来我们需要使用keydown事件了。

你可能才到事情没那么简单。在Opera和Safari里面keydown事件只能触发一次,所以当用户按下键之后,元素移动一次之后就不动了。在这些浏览器中我们需要keypress。

所以理想情况下,我们使用keypress,如果不支持就是用keydown。但是怎么切换事件呢?你又怎么知道keypress在这个时候不能用呢?

我的解决办法就是给keypress事件设置一个事件处理程序。如果这个程序执行了说明支持keypress,我们就可以安全的切换了。

startDragKeys函数用来设置keydown和keypress事件:

复制代码 代码如下:

addEventSimple(document,'keydown',dragDrop.dragKeys);
addEventSimple(document,'keypress',dragDrop.switchKeyEvents);

首先keydown触发完成拖拽的dragKeys函数。这是第一个触发的事件,而且元素总会移动。然后我们做其他的话,那么元素在Opera和Safari1.3里面移动一次以后就会停止。
这就是为什么我们还需要keypress。第一个keypress事件会触发switchKeyEvents函数,这个函数会调整事件处理程序:
复制代码 代码如下:

switchKeyEvents: function () {
removeEventSimple(document,'keydown',dragDrop.dragKeys);
removeEventSimple(document,'keypress',dragDrop.switchKeyEvents);
addEventSimple(document,'keypress',dragDrop.dragKeys);
},

他会先删除掉原来的事件处理程序,然后将keypress设置为触发dragKeys。因为这个函数只会在支持他的浏览器里面执行,所以我们只在这些浏览器里面将keydown改为keypress。
初始键盘代码
当用户点击了连接激活了元素,那么就会调用startDragKeys。
复制代码 代码如下:

startDragKeys: function () {
dragDrop.startDrag(this.relatedElement);
dragDrop.dXKeys = dragDrop.dYKeys = 0;
addEventSimple(document,'keydown',dragDrop.dragKeys);
addEventSimple(document,'keypress',dragDrop.switchKeyEvents);
this.blur();
return false;
},

首先会调用我们之前讨论过的startDrag函数。他会给这个函数传递relatedElement,也就是要拖拽的元素。
然后将dXKeys和dYKeys设置为0。这些变量用来跟踪元素的位移。
然后设置事件处理程序,上面已经讨论过了。
然后移除刚才点击的链接的焦点。我这样做是因为Enter键会释放元素,但是如果不移除焦点,当用户点击了Enter键之后,元素被释放,但是链接却再次被Enter点击,又成了可拖动的模式。如果我们移除焦点,那么问题就不存在了。
最后返回false来阻止默认动作。
通过键盘拖拽
dragKeys负责键盘拖拽:
复制代码 代码如下:

dragKeys: function(e) {
var evt = e || window.event;
var key = evt.keyCode;

我们首先读取键盘的键值。
然后我们使用switch语句来决定我们怎么做。这部分的目的是更新dXKeys和dYKeys的值,就可以通过设置元素的位置来移动元素了。
复制代码 代码如下:

switch (key) {
case 37: // left
case 63234:
dragDrop.dXKeys -= dragDrop.keySpeed;
break;
case 38: // up
case 63232:
dragDrop.dYKeys -= dragDrop.keySpeed;
break;
case 39: // right
case 63235:
dragDrop.dXKeys += dragDrop.keySpeed;
break;
case 40: // down
case 63233:
dragDrop.dYKeys += dragDrop.keySpeed;
break;

作者通过设置keySpeed来确定每次移动的像素大小。当用户点击左方向键,就减去keySpeed。
http://www.quirksmode.org/js/dragdrop.html
转载请保留以下信息
作者:北玉(tw:@rehawk)


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3