拖放(二):鼠标事件实现拖放

原生的拖放事件(drag and drop)属于HTML5的接口,对它的兼容性可以通过caniuse网站看到。

拖放过程

根据拖放的过程来考虑,拖放的效果其实是实现元素对鼠标的跟随,将鼠标的坐标位移设置到元素上。

所以,可以使用鼠标操作的对应事件mousedown, mousemove, mouseup实现拖放

  1. 鼠标按下,计算鼠标与被拖动元素偏移值
  2. 鼠标移动,更新被拖动元素的坐标
  3. 鼠标释放,设置元素为不可拖动

image

这里最关键的地方就是计算鼠标按下之处与被拖动元素的偏移,这样在无论鼠标移动到哪里,元素的位置也就是确定的,二者可以由如下方式获取

  • 鼠标坐标:clientX, clientYpageX, pageY都可以用来获取鼠标当前页面的坐标,但是IE8及以下的浏览器并不支持pageX, pageY
  • 元素坐标:被拖动的元素定位需要被设置为absolute,其父元素对应设置为相对定位,那么可以使用offsetLeft, offsetTop获取对应位置。

二者之差确定偏移值offset

1
2
3
4
5
6
box.onmousedown = function(e) {
var e = e || window.event;
offset.x = e.clientX - this.offsetLeft;
offset.y = e.clientY - this.offsetTop;
isDraging = true;
}

移动过程中就可以把获取到的鼠标坐标减去偏移值确定元素具体位置

1
2
3
4
5
6
7
document.onmousemove = function(e) {
var e = e || window.event;
if (isDraging) {
box.style.left = e.clientX - offset.x + 'px';
box.style.top = e.clientY - offset.y + 'px';
}
}

拖放范围限定

实际操作过程中并不希望元素满屏幕的乱跑,需要把它关在笼子里,因此需要限制它的活动范围。

父元素的四条边作为元素移动的边界值,转换成被拖拽元素的坐标值就是:

  • left, top值不能小于0
  • 元素left值与width值的不大于父元素宽度
  • 元素top值与height值的不大于父元素的高度

经过改写的mousemove函数为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
document.onmousemove = function(e) {
var e = e || window.event;
var maxX = wrap.clientWidth - box.offsetWidth;
var maxY = wrap.clientHeight - box.offsetHeight;
var moveX = Math.min(Math.max(0, (e.clientX - offset.x)), maxX);
var moveY = Math.min(Math.max(0, (e.clientY - offset.y)), maxY);
if (isDraging) {
box.style.left = moveX + 'px';
box.style.top = moveY + 'px';
}
}

拖放实例

参考资料

http://www.imooc.com/learn/60