博主的前端入门知识是在慕课网学的,当时有个demo,就是在网页模拟一个QQ面板的拖动效果(如图,用两个DIV代替。。。效果是拖动中间的DIV,整个DIV跟着移动),今天来总结记录一下。
思路是当鼠标按下时,开始计算元素距离屏幕左边缘和上边缘的距离,并同步赋予元素。这里的关键点是对于JS中元素与根元素(或者指定父级元素)的距离的运用,即offset。
首先假设外层盒子叫out,中间盒子叫center。当鼠标在center按下时为out添加事件:
1 function drag () { 2 var center = document.getElementById('center') 3 center.onmousedown = client // 获取中间盒子,按下鼠标时添加事件 4 }
并且获取out的当前位置(clientX,clientY)(这里的参照系是当前窗口,若将浏览器窗口缩小,则可移动区域减小),再获取out距离窗口边缘的位置坐标(offsetLeft,offsetTop),此处没有设置参考的父元素,所以以根元素为参照物,即body。
取两者差值,就是整个DIV应该变化的坐标量。这时将out的坐标与变化量相加,就得到了整个DIV的新坐标值。用onmousemove随时更新DIV的坐标,就得到了拖动的效果。
1 function client (eve) { 2 eve = eve || window.event // 兼容性 3 var out = document.getElementById('out') 4 var disX = eve.clientX - out.offsetLeft // 鼠标点击位置跟out块的左边框距离 5 var disY = eve.clientY - out.offsetTop // 鼠标点击位置跟out块的上边框距离 6 document.onmousemove = function (event) { 7 event = event || window.event 8 mov(event, disX, disY) 9 console.log('eve.clientX' + eve.clientX) 10 console.log('disX' + disX) 11 console.log('out.offsetLeft' + out.offsetLeft) 12 } 13 document.onmouseup = function () { 14 document.onmousemove = null 15 document.onmouseup = null // 释放鼠标时清空事件 16 } 17 }
为防止盒子移动到窗口外面,需要进行边缘检测,由于窗口的坐标系以屏幕左上角为原点,所以左边检测和上边检测只需要看鼠标的坐标—out距离窗口左边框(或上边框)的距离是否等于0就行。
右侧检测需要计算盒子距离左边缘的距离+盒子本身的宽度是否超过了浏览器窗口本身的宽度,浏览器本身可见区域的宽度为clientWidth,盒子本身的宽度是out.offsetWidth,这两者的差就是鼠标在x方向移动的最大值。当鼠标移动到最大值时说明盒子已经移动到了右侧屏幕边缘。底部与右侧相似。
1 function mov (e, posx, posy) { 2 e = e || window.event 3 var out = document.getElementById('out') 4 var finalLeft = e.clientX - posx // out盒子左边框距离左窗口的距离 5 var finalHeight = e.clientY - posy // out盒子上边框距离上窗口的距离 6 var diffWidth = document.documentElement.clientWidth - out.offsetWidth || document.body.clientWidth - out.offsetWidth // 兼容性获取当前窗口的宽度-out盒子的宽度 7 var diffHeight = document.documentElement.clientHeight - out.offsetHeight || document.body.clientWidth - out.offsetWidth // 兼容性获取当前窗口的高度-out盒子的高度 8 if (finalLeft <= 0) { 9 finalLeft = 0 10 } 11 if (finalHeight <= 0) { 12 finalHeight = 0 13 } 14 if (finalLeft >= diffWidth) { 15 finalLeft = diffWidth 16 } 17 if (finalHeight >= diffHeight) { 18 finalHeight = diffHeight 19 } // 设置坐标,使盒子不超出窗口 20 out.style.left = finalLeft + 'px' 21 out.style.top = finalHeight + 'px' 22 } 23 window.onload = drag