好的魄懂,這次來看看用純js如何實(shí)現(xiàn)拖拽運(yùn)動(dòng)。源碼已上傳到github,需要的可以下載 https://github.com/17714574361/drag . 想想怎么寫呢锨并,好的吧谷徙,我承認(rèn)直接想對(duì)于像我這種剛?cè)腴T的小白來說是不可能的剪决,那么我們來畫一個(gè)圖,
圖中歧匈,黑色的框表示瀏覽器,藍(lán)色的框表示擁有定位元素的div王带,綠色的表示要拖拽的div淑蔚,紅色的點(diǎn)表示鼠標(biāo)按下的位置
那么我們?cè)鯓硬拍芡献兀瑳]錯(cuò)愕撰,就是你想的這樣刹衫,先按下鼠標(biāo)左鍵,不松開搞挣,然后再移動(dòng)鼠標(biāo)即可带迟,是不是很簡(jiǎn)單,那到底該怎么用代碼實(shí)現(xiàn)呢囱桨?
當(dāng)鼠標(biāo)按下的時(shí)候仓犬,我們給綠色的div添加一個(gè)鼠標(biāo)事件onmousedown
html代碼
<body>
<div id="wrap">
<div id="box"></div>
</div>
</body>
css代碼
#wrap {
width: 600px;
height: 500px;
border: 1px solid #ccc;
position: relative;
margin: 50px auto;
}
#box {
width: 100px;
height: 100px;
background: seagreen;
position: absolute;
left: 0;
top: 0;
}
js代碼
window.onload = function () {
let box = $("box"); //相當(dāng)于document.getElementById(id),這是封裝的函數(shù)
//給綠色的div添加onmousedown事件
box.onmousedown = function () {
}
}
然后在計(jì)算綠色div的left和top值即可舍肠,那么如何計(jì)算呢搀继,看圖:
我們先看如何計(jì)算left值(紅線),
可以圖中知道翠语,橙線是藍(lán)色div的offsetLeft叽躯,黑線是綠色div的offsetLeft,棕線是鼠標(biāo)距離瀏覽器左邊的距離肌括。所以我們可以這樣計(jì)算left值点骑,先計(jì)算出鼠標(biāo)到綠色div的左側(cè)邊緣的距離,然后才能計(jì)算出left值们童。top值的計(jì)算方法也是一樣畔况,我就步描述了。
window.onload = function () {
let box = $("box");
let wrap = $("wrap");
//給綠色的div添加onmousedown事件
box.onmousedown = function (ev) {
let e = ev || window.event;
//計(jì)算出鼠標(biāo)按下的點(diǎn)到box的左側(cè)邊緣和上側(cè)邊緣
let restLeft = e.clientX - wrap.offsetLeft - box.offsetLeft;
let restTop = e.clientY - wrap.offsetTop - box.offsetTop;
//移動(dòng)的時(shí)候計(jì)算left和top值慧库,這樣每次移動(dòng)都會(huì)生效
box.onmousemove = function (ev) {
let e = ev || window.event;
//計(jì)算出left值和top值
let boxLeft = e.clientX - restLeft - wrap.offsetLeft;
let boxTop = e.clientY - restTop - wrap.offsetTop;
//設(shè)置left,top值
box.style.left = boxLeft + "px";
box.style.top = boxTop + "px";
}
}
}
好馋嗜,那么問題就來了齐板,div是可以拖拽,但是當(dāng)拖拽速度過快葛菇,鼠標(biāo)不在div上面時(shí)甘磨,就沒法托拽了,此時(shí)眯停,這樣解決济舆,將onmousemove事件的對(duì)象改為document即可,這樣無論你多塊都可以莺债,div都會(huì)跟著一起移動(dòng)滋觉。
好了签夭,上面的問題是解決了,但是當(dāng)鼠標(biāo)松開的時(shí)候椎侠,div還是跟著一起移動(dòng)第租,我們可以這樣解決,我們給生個(gè)頁面添加一個(gè)onmouseup事件我纪,在inmouseup回掉函數(shù)里將onmousemove事件設(shè)為銷毀慎宾,并將onmouseup事件銷毀。代碼
window.onload = function () {
let box = $("box");
let wrap = $("wrap");
//給綠色的div添加onmousedown事件
box.onmousedown = function (ev) {
let e = ev || window.event;
//計(jì)算出鼠標(biāo)按下的點(diǎn)到box的左側(cè)邊緣和上側(cè)邊緣
let restLeft = e.clientX - wrap.offsetLeft - box.offsetLeft;
let restTop = e.clientY - wrap.offsetTop - box.offsetTop;
//移動(dòng)的時(shí)候計(jì)算left和top值浅悉,這樣每次移動(dòng)都會(huì)生效
document.onmousemove = function (ev) {
let e = ev || window.event;
//計(jì)算出left值和top值
let boxLeft = e.clientX - restLeft - wrap.offsetLeft;
let boxTop = e.clientY - restTop - wrap.offsetTop;
//設(shè)置left趟据,top值
box.style.left = boxLeft + "px";
box.style.top = boxTop + "px";
};
box.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
};
};
現(xiàn)在拖拽事件就實(shí)現(xiàn)了。
我們現(xiàn)在再增加一個(gè)需求术健,限時(shí)拖拽的范圍汹碱,我們?nèi)绾巫尡煌献У膁iv限定在wrap這個(gè)框內(nèi)。其實(shí)這個(gè)很好實(shí)現(xiàn)苛坚,我們只需分別計(jì)算left比被,top的最大值和最小值。
window.onload = function () {
let box = $("box");
let wrap = $("wrap");
//給綠色的div添加onmousedown事件
box.onmousedown = function (ev) {
let e = ev || window.event;
//計(jì)算出鼠標(biāo)按下的點(diǎn)到box的左側(cè)邊緣和上側(cè)邊緣
let restLeft = e.clientX - wrap.offsetLeft - box.offsetLeft;
let restTop = e.clientY - wrap.offsetTop - box.offsetTop;
//移動(dòng)的時(shí)候計(jì)算left和top值泼舱,這樣每次移動(dòng)都會(huì)生效
document.onmousemove = function (ev) {
let e = ev || window.event;
//計(jì)算出left值和top值
let boxLeft = e.clientX - restLeft - wrap.offsetLeft;
let boxTop = e.clientY - restTop - wrap.offsetTop;
//限制范圍
let maxLeft = wrap.offsetWidth - box.offsetWidth;
let maxTop = wrap.offsetHeight - box.offsetHeight;
let minLeft = 0;
let minTop = 0;
if (boxLeft < minLeft) {
boxLeft = minLeft;
}
if (boxLeft > maxLeft) {
boxLeft = maxLeft;
}
if (boxTop < minTop) {
boxTop = minTop;
}
if (boxTop > maxTop) {
boxTop = maxTop;
}
//設(shè)置left等缀,top值
box.style.left = boxLeft + "px";
box.style.top = boxTop + "px";
};
box.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
}
return false;
};
};
現(xiàn)在我們是真的寫完了。好娇昙,完結(jié)尺迂。我想說其實(shí)還有一個(gè)問題,就是兼容型問題冒掌,上面的代碼帶低版本IE中是會(huì)出問題的噪裕,問題就是如果拖拽范圍之內(nèi)有文字,低版本IE會(huì)選中文字股毫,可能不會(huì)拖拽膳音,那我們?cè)趺唇鉀Q呢。
針對(duì)IE這個(gè)問題有個(gè)處理方法就是使用setCapture方法在oBox元素和下面的元素中間添加了一個(gè)透明層
window.onload = function () {
let box = $("box");
let wrap = $("wrap");
//給綠色的div添加onmousedown事件
box.onmousedown = function (ev) {
let e = ev || window.event;
//計(jì)算出鼠標(biāo)按下的點(diǎn)到box的左側(cè)邊緣和上側(cè)邊緣
let restLeft = e.clientX - wrap.offsetLeft - box.offsetLeft;
let restTop = e.clientY - wrap.offsetTop - box.offsetTop;
// 針對(duì)低版本IE的方法铃诬,setCapture方法在oBox元素和下面的元素中間添加了一個(gè)透明層
if (box.setCapture) {
box.setCapture();
}
//移動(dòng)的時(shí)候計(jì)算left和top值祭陷,每次移動(dòng)都會(huì)生效
document.onmousemove = function (ev) {
let e = ev || window.event;
//計(jì)算出left值和top值
let boxLeft = e.clientX - restLeft - wrap.offsetLeft;
let boxTop = e.clientY - restTop - wrap.offsetTop;
//限制范圍
let maxLeft = wrap.offsetWidth - box.offsetWidth;
let maxTop = wrap.offsetHeight - box.offsetHeight;
let minLeft = 0;
let minTop = 0;
if (boxLeft < minLeft) {
boxLeft = minLeft;
}
if (boxLeft > maxLeft) {
boxLeft = maxLeft;
}
if (boxTop < minTop) {
boxTop = minTop;
}
if (boxTop > maxTop) {
boxTop = maxTop;
}
//設(shè)置left,top值
box.style.left = boxLeft + "px";
box.style.top = boxTop + "px";
};
box.onmouseup = function () {
//銷毀onmousemove和onmouseup事件
document.onmousemove = null;
document.onmouseup = null;
// 去掉透明層
if (box.releaseCapture) {
box.releaseCapture();
}
};
//阻止瀏覽器默認(rèn)行為
return false;
};
};
這下是真的寫完了Hは1尽!P恰O牒薄!C拐恰0醇邸2咽省!
源碼已上傳到github,需要的可以下載 https://github.com/17714574361/drag