1.鼠标行为坐标系

clientX/Y :鼠标坐标相对于当前可视区域的坐标(不包括滚动区域)
pageX/Y: 鼠标位置相对于当前文档的坐标,(包含滚动条的距离)
screenX/Y:鼠标位置相对于屏幕的坐标
e.x/y : 与clientX/Y相同,但firbox不兼容
offsetX/Y: 鼠标位置相对于块级元素的坐标(包含边框)

2.鼠标拖曳坐标

1.鼠标事件由mousedown => mouseup => click的顺序执行,要想达到鼠标拖曳的效果,我们实际上就是要拿到鼠标距离窗口的距离然后进行额外的优化即可
我将拖曳函数封装到element的原型上,用的时候可以直接访问

  1. Element.prototype.dragclick = function (fn) {
  2. let sTime = 0,
  3. eTime = 0,
  4. infoArr = [],
  5. elWidth = getStyles(this, 'width'), // 盒子宽高
  6. elHeight = getStyles(this, 'height'),
  7. wWidth = getViewportSize().width, // 当前视口宽高
  8. wHeight = getViewportSize().height
  9. // 封装 物体拖曳函数
  10. elemDrag.call(this)
  11. function elemDrag() {
  12. let x,
  13. y,
  14. _self = this
  15. addEvent(_self, 'mousedown', function (e) {
  16. sTime = new Date().getTime()
  17. var e = e || window.event
  18. x = pagePos(e).X - getStyles(_self, 'left')
  19. y = pagePos(e).Y - getStyles(_self, 'top')
  20. infoArr = [getStyles(_self, 'left'), getStyles(_self, 'top')]
  21. addEvent(document, 'mousemove', mouseMove)
  22. addEvent(document, 'mouseup', mouseUp)
  23. cancelBubble(e)
  24. preventDefeaultEvent(e)
  25. })
  26. function mouseMove(e) {
  27. var e = e || window.event,
  28. eleLeft = pagePos(e).X - x,
  29. eleTop = pagePos(e).Y - y
  30. if (eleLeft <= 0) {
  31. eleLeft = 0
  32. } else if (eleLeft >= wWidth - elWidth) {
  33. eleLeft = wWidth - elWidth
  34. // console.log(eleLeft)
  35. }
  36. if (eleTop <= 0) {
  37. eleTop = 0
  38. } else if (eleTop >= wHeight - elHeight) {
  39. eleTop = wHeight - elHeight - 1
  40. }
  41. _self.style.left = eleLeft + 'px'
  42. _self.style.top = eleTop + 'px'
  43. }
  44. function mouseUp(e) {
  45. eTime = new Date().getTime()
  46. if (eTime - sTime < 300) {
  47. fn()
  48. _self.style.left = infoArr[0] + 'px'
  49. _self.style.top = infoArr[1] + 'px'
  50. }
  51. var e = e || window.event
  52. removeEvent(document, 'mousemove', mouseMove)
  53. removeEvent(document, 'mouseup', mouseUp)
  54. }
  55. }
  56. }

其中需要对很多地方做优化

  1. 比如既可以拖曳盒子,点击也能跳转,我们就需要判断什么时候跳转什么时候拖曳,
  2. 边界处理:盒子不能超过浏览器视口(既不能出现滚动条) 举个例子: 盒子的最大右偏移量应该等于视口的宽度-盒子的宽度
  3. 在盒子区域内点击反键,显示另外一个盒子,并且对它出现的位置做出处理
  4. 点击2次才才可以跳转,点击一次无效果

完结版:

Element.prototype.dragclick = function (fn, menu) {
    let sTime = 0,
        eTime = 0,
        cStime = 0,
        cEtime = 0,
        counter = 0,
        infoArr = [],
        t,
        elWidth = getStyles(this, 'width'), // 盒子宽高
        elHeight = getStyles(this, 'height'),
        wWidth = getViewportSize().width, // 当前视口宽高
        wHeight = getViewportSize().height,
        mWidth = getStyles(menu, 'width'),
        mHeight = getStyles(menu, 'height')
    // 封装 物体拖曳函数
    elemDrag.call(this)
    function elemDrag() {
        let x,
            y,
            _self = this
        addEvent(_self, 'mousedown', function (e) {
            var e = e || window.event,
                btnCode = e.button
            if (btnCode === 2) {
                var mLeft = pagePos(e).X,
                    mTop = pagePos(e).Y
                if (mLeft <= 0) {
                    mLeft = 0
                } else if (mLeft >= wWidth - mWidth) {
                    mLeft = pagePos(e).X - mWidth
                }
                if (mTop <= 0) {
                    mTop = 0
                } else if (mTop >= wHeight - mHeight) {
                    mTop = pagePos(e).Y - mHeight
                }
                menu.style.left = mLeft + 'px'
                menu.style.top = mTop + 'px'
                menu.style.display = 'block'
            } else if (btnCode === 0) {
                sTime = new Date().getTime()
                x = pagePos(e).X - getStyles(_self, 'left')
                y = pagePos(e).Y - getStyles(_self, 'top')
                infoArr = [getStyles(_self, 'left'), getStyles(_self, 'top')]
                addEvent(document, 'mousemove', mouseMove)
                addEvent(document, 'mouseup', mouseUp)
                cancelBubble(e)
                preventDefeaultEvent(e)
            }
        })
        addEvent(document, 'contextmenu', function (e) {
            var e = e || window.event
            preventDefeaultEvent(e)
        })
        addEvent(document, 'click', function (e) {
            menu.style.display = 'none'
        })
        addEvent(menu, 'click', function (e) {
            var e = e || window.event
            cancelBubble(e) // 阻止事件往document上冒泡
        })
        function mouseMove(e) {
            menu.style.display = 'none'
            var e = e || window.event,
                eleLeft = pagePos(e).X - x,
                eleTop = pagePos(e).Y - y
            if (eleLeft <= 0) {
                eleLeft = 0
            } else if (eleLeft >= wWidth - elWidth) {
                eleLeft = wWidth - elWidth
                // console.log(eleLeft)
            }

            if (eleTop <= 0) {
                eleTop = 0
            } else if (eleTop >= wHeight - elHeight) {
                eleTop = wHeight - elHeight - 1
            }
            _self.style.left = eleLeft + 'px'
            _self.style.top = eleTop + 'px'
        }
        function mouseUp(e) {
            var e = e || window.event
            eTime = new Date().getTime()
            if (eTime - sTime < 300) {
                _self.style.left = infoArr[0] + 'px'
                _self.style.top = infoArr[1] + 'px'
                counter++
                if (counter === 1) {
                    cStime = new Date().getTime()
                }
                if (counter === 2) {
                    cEtime = new Date().getTime()
                }
                if (cStime && cEtime && cEtime - cStime < 200) {
                    fn()
                }
                t = setTimeout(function () {
                    cStime = 0
                    cEtime = 0
                    counter = 0
                    clearTimeout(t)
                }, 500)
            }
            removeEvent(document, 'mousemove', mouseMove)
            removeEvent(document, 'mouseup', mouseUp)
        }
    }
}