vue實(shí)現(xiàn)盒子內(nèi)拖動(dòng)方塊移動(dòng)的示例代碼
vue實(shí)現(xiàn)盒子內(nèi)拖動(dòng)方塊移動(dòng)
本文采用vue2的options api。
1. 創(chuàng)建盒子與方塊
最簡(jiǎn)單的父子嵌套盒子,子盒子絕對(duì)定位。
<template>
<div class="Drag">
<div class="scroll_thumb"></div>
</div>
</template>
<script>
export default {
name: "Drag",
};
</script>
<style scoped>
.Drag {
position: relative;
width: 1000px;
height: 600px;
border: 1px solid #333;
margin: 100px auto;
}
.Drag .scroll_thumb {
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
background-color: gold;
}
</style>2.獲取父盒子在文檔的位置信息
使用getBoundingClientRect API獲取

<template>
<div ref="drag" class="Drag">
<div class="scroll_thumb"></div>
</div>
</template>
<script>
export default {
name: "Drag",
data() {
return {
boxRect: {}, //父盒子位置信息
};
},
mounted() {
this.setBoxRect();
// 窗口變化時(shí)重新獲取數(shù)據(jù)
window.addEventListener("resize", this.setBoxRect);
},
beforeDestroy() {
window.removeEventListener("resize", this.setBoxRect);
},
methods: {
setBoxRect() {
//獲取父盒子在文檔的位置信息
this.boxRect = this.$refs.drag.getBoundingClientRect();
},
},
}
</script>3.監(jiān)聽(tīng)鼠標(biāo)點(diǎn)擊事件
<template>
<div ref="drag" class="Drag">
<div class="scroll_thumb" @mousedown="mousedown"></div>
</div>
</template>
<script>
export default {
methods: {
// 點(diǎn)擊鼠標(biāo)按鍵觸發(fā)
mousedown() {
// 判斷是否是鼠標(biāo)左鍵
if (event.button !== 0) return;
// 監(jiān)聽(tīng)鼠標(biāo)移動(dòng)與彈起事件
document.addEventListener("mousemove", this.mousemove);
document.addEventListener("mouseup", this.mouseup);
},
// 鼠標(biāo)移動(dòng)觸發(fā)
mousemove(event) {
// 此為關(guān)鍵代碼,下面進(jìn)行分析
},
// 鼠標(biāo)按鍵彈起時(shí)移除監(jiān)聽(tīng)的時(shí)間
mouseup() {
this.removeMouseEvent()
},
removeMouseEvent() {
document.removeEventListener("mousemove", this.mousemove);
document.removeEventListener("mouseup", this.mouseup);
},
},
};
</script>4.計(jì)算方塊跟隨鼠標(biāo)移動(dòng)
<template>
<div ref="drag" class="Drag">
<!-- 動(dòng)態(tài)計(jì)算方塊的top與left -->
<div
class="scroll_thumb"
:style="{
width: `${thumbW}px`,
height: `${thumbH}px`,
top: `${thumbTop}px`,
left: `${thumbLeft}px`,
}"
@mousedown="mousedown"
></div>
</div>
</template>
<script>
export default {
name: "Drag",
data() {
return {
// 方塊的位置
thumbTop: 0,
thumbLeft: 0,
// 定義方塊的寬高
thumbW: 20,
thumbH: 20,
boxRect: {},
};
},
methods: {
mousemove(event) {
// 阻止瀏覽器默認(rèn)的行為
event.preventDefault();
// 停止冒泡
event.stopPropagation();
// 方塊定位的值 = 鼠標(biāo)位置 - 方塊自身寬高/2 - 父盒子左上角位置的值
// ps1:方塊自身寬高/2,作用是使鼠標(biāo)的位置始終在方塊的中心點(diǎn)
// ps2: 父盒子左上角位置的值,是因?yàn)閑vent.clientX/Y是采用文檔定位,而thumbLeft是絕對(duì)定位,所以要矯正偏移的值
this.thumbLeft = event.clientX - this.thumbW / 2 - this.boxRect.left;
this.thumbTop = event.clientY - this.thumbH / 2 - this.boxRect.top;
},
},
};
</script>到此已經(jīng)能夠?qū)崿F(xiàn)鼠標(biāo)拖動(dòng)了,但是方塊可以拖動(dòng)到任意位置,下面我們將進(jìn)行限制。
5.將方塊限制在盒子內(nèi)移動(dòng)
<template>
<div ref="drag" class="Drag">
<!-- 動(dòng)態(tài)計(jì)算方塊的top與left -->
<div
class="scroll_thumb"
:style="{
width: `${thumbW}px`,
height: `${thumbH}px`,
top: `${thumbTop}px`,
left: `${thumbLeft}px`,
}"
@mousedown="mousedown"
></div>
</div>
</template>
<script>
export default {
name: "Drag",
data() {
return {
// 方塊的位置
thumbTop: 0,
thumbLeft: 0,
// 定義方塊的寬高
thumbW: 20,
thumbH: 20,
boxRect: {},
};
},
methods: {
mousemove(event) {
event.preventDefault();
event.stopPropagation();
this.thumbLeft = event.clientX - this.thumbW / 2 - this.boxRect.left;
this.thumbTop = event.clientY - this.thumbH / 2 - this.boxRect.top;
// 調(diào)用限制
this.setLimit();
},
setLimit() {
// 獲取方塊的右側(cè)與底部的值
const thumbRight = this.thumbLeft + this.thumbW;
const thumbBottom = this.thumbTop + this.thumbH;
// 當(dāng)方塊的位置超過(guò)頂部或左側(cè),將定位的值設(shè)置為0
if (this.thumbLeft <= 0) {
this.thumbLeft = 0;
}
if (this.thumbTop <= 0) {
this.thumbTop = 0;
}
// 當(dāng)方塊的位置超過(guò)底部或者右側(cè),將定位的值設(shè)置為父盒子寬高-方塊本身寬高的值
if (thumbRight >= this.boxRect.width) {
this.thumbLeft = this.boxRect.width - this.thumbW;
}
if (thumbBottom >= this.boxRect.height) {
this.thumbTop = this.boxRect.height - this.thumbH;
}
},
},
};
</script>6.完整代碼
<template>
<div ref="drag" class="Drag">
<!-- 動(dòng)態(tài)計(jì)算方塊的top與left -->
<div
class="scroll_thumb"
:style="{
width: `${thumbW}px`,
height: `${thumbH}px`,
top: `${thumbTop}px`,
left: `${thumbLeft}px`,
}"
@mousedown="mousedown"
></div>
</div>
</template>
<script>
export default {
name: "Drag",
data() {
return {
thumbTop: 0,
thumbLeft: 0,
thumbW: 20,
thumbH: 20,
boxRect: {},
};
},
mounted() {
this.setBoxRect();
window.addEventListener("resize", this.setBoxRect);
},
beforeDestroy() {
window.removeEventListener("resize", this.setBoxRect);
this.removeMouseEvent();
},
methods: {
setBoxRect() {
this.boxRect = this.$refs.drag.getBoundingClientRect();
},
mousedown(event) {
// 判斷是否是鼠標(biāo)左鍵
if (event.button !== 0) return;
document.addEventListener("mousemove", this.mousemove);
document.addEventListener("mouseup", this.mouseup);
},
mousemove(event) {
event.preventDefault();
event.stopPropagation();
this.thumbLeft = event.clientX - this.thumbW / 2 - this.boxRect.left;
this.thumbTop = event.clientY - this.thumbH / 2 - this.boxRect.top;
this.setLimit();
},
setLimit() {
const thumbRight = this.thumbLeft + this.thumbW;
const thumbBottom = this.thumbTop + this.thumbH;
if (this.thumbLeft <= 0) {
this.thumbLeft = 0;
}
if (this.thumbTop <= 0) {
this.thumbTop = 0;
}
if (thumbRight >= this.boxRect.width) {
this.thumbLeft = this.boxRect.width - this.thumbW;
}
if (thumbBottom >= this.boxRect.height) {
this.thumbTop = this.boxRect.height - this.thumbH;
}
},
mouseup() {
this.removeMouseEvent();
},
removeMouseEvent() {
document.removeEventListener("mousemove", this.mousemove);
document.removeEventListener("mouseup", this.mouseup);
},
},
};
</script>
<style scoped>
.Drag {
position: relative;
width: 1000px;
height: 600px;
border: 1px solid #333;
margin: 100px auto;
}
.Drag .scroll_thumb {
position: absolute;
background-color: gold;
}
</style>7.效果

8.應(yīng)用
筆者做這個(gè)案例是為了實(shí)現(xiàn)虛擬列表的滾動(dòng)條做的技術(shù)儲(chǔ)備,還有其他應(yīng)用或想法歡迎評(píng)論區(qū)留言。
以上就是vue實(shí)現(xiàn)盒子內(nèi)拖動(dòng)方塊移動(dòng)的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于vue實(shí)現(xiàn)盒子內(nèi)方塊移動(dòng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue實(shí)現(xiàn)單點(diǎn)登錄的方式匯總
最近項(xiàng)目停工了,RageFrame的學(xué)習(xí)暫時(shí)告一段落,這一篇給大家分享下有關(guān)單點(diǎn)登錄的相關(guān)知識(shí),并提供一些demo給大家參考,對(duì)vue單點(diǎn)登錄的實(shí)現(xiàn)方式感興趣的朋友一起看看吧2021-11-11
簡(jiǎn)單學(xué)習(xí)vue指令directive
這篇文章主要和大家一起簡(jiǎn)單學(xué)習(xí)一下vue指令:directive,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
mpvue項(xiàng)目中使用第三方UI組件庫(kù)的方法
這篇文章主要介紹了mpvue項(xiàng)目中使用第三方UI組件庫(kù)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09

