进一步改进,不使用mouseup事件,这样就减少了错过mouseup事件带来的鼠标粘着卡壳的问题。但由于标准浏览器不会自动切换e.button和e.which的值,我被迫动用一个功能键Shirt来停止鼠标拖拽。 01. var Drag = function (id){ 02. var el = document.getElementById(id); 03. el.style.position = "absolute" ; 04. var drag = function (e){ 05. var e = e || window.event, 06. button = e.button || e.which; 07. if (button == 1 && e.shiftKey == false ){ 08. el.style.cursor = "pointer" ; 09. !+ "\v1" ? document.selection.empty() : window.getSelection().removeAllRanges(); 10. el.style.left = e.clientX - el.offset_x + "px" ; 11. el.style.top = e.clientY - el.offset_y + "px" ; 12. el.innerHTML = parseInt(el.style.left,10)+ " x " +parseInt(el.style.top,10); 13. } else { 14. document.onmousemove = null ; 15. } 16. } 17. var dragstart = function (e){ 18. e = e || window.event; 19. el.offset_x = e.clientX - el.offsetLeft; 20. el.offset_y = e.clientY - el.offsetTop; 21. el.style.zIndex = ++Drag.z; 22. document.onmousemove = drag; 23. return false ; 24. } 25. Drag.z = 999; 26. el.onmousedown = dragstart; 27. } 虽然不绑定mouseup的确在IE爽到high起,但在火狐等浏览要多按一个键才能终止拖动,怎么说也对用户体验造成影响,因此当一种知识学学就算了。我们还是选择方案2。 接着下来我们为方案扩展一下功能。首先范围拖动,就是存在一个让它在上面拖动的容器。如果存在容器,我们就取得其容器的四个点的坐标,与拖动元素的四个点的坐标比较,从而修正top与left。由于我已经实现了getCoords函数,取得页面上某一点的坐标易如反掌。同时这样做,我们就不用把此容器设置成offsetParent。总之,多一事不如少一事。 01. var getCoords = function (el){ 02. var box = el.getBoundingClientRect(), 03. doc = el.ownerDocument, 04. body = doc.body, 05. html = doc.documentElement, 06. clientTop = html.clientTop || body.clientTop || 0, 07. clientLeft = html.clientLeft || body.clientLeft || 0, 08. top = box.top + (self.pageYOffset || html.scrollTop || body.scrollTop ) - clientTop, 09. left = box.left + (self.pageXOffset || html.scrollLeft || body.scrollLeft) - clientLeft 10. return { 'top' : top, 'left' : left }; 11. }; 接着我们要取得容器的四个点的坐标: 1. _cCoords = getCoords(container), 2. _cLeft = _cCoords.left, 3. _cTop = _cCoords.top, 4. _cRight = _cLeft + container.clientWidth, 5. _cBottom = _cTop + container.clientHeight; 接着是拖动元素的四个点的坐标: 1. var _left = el.offsetLeft, 2. _top = el.offsetTop, 3. _right = _left + el.offsetWidth, 4. _bottom = _top + el.offsetHeight, 但是这样取得的是没有拖动前的坐标,拖动时的坐标在上面的方案2也已给出了: 1. var _left = e.clientX - el.offset_x, 2. _top = e.clientY - el.offset_y, 修正坐标很简单,如果拖动元素在左边或上边超出容器,就让拖动元素的top与left取容器的_cLeft或_cTop值,如果从右边超出容器,我们用_cRight减去容器的宽度再赋给拖动元素的top,下边的处理相仿。 01. if (_left < _cLeft){ 02. _left = _cLeft 03. } 04. if (_top < _cTop){ 05. _top = _cTop 06. } 07. if (_right > _cRight){ 08. _left = _cRight - el.offsetWidth; 09. } 10. if (_bottom > _cBottom){ 11. _top = _cBottom - el.offsetHeight; 12. } 13. el.style.left = _left + "px" ; 14. el.style.top = _top + "px" ; 水平锁定与垂直锁直也是两个很常用的功能,我们也来实现它。原理很简单,在开始拖动时就把top与left保存起来,待到拖动时再赋给它就行了。代码请直接看运行框的代码: (责任编辑:admin) |