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