天天看点

实现vue项目下多元素限定边界的拖拽功能

要求:实现多个元素在限定的范围内自由拖拽

(除vue的其他项目也可以用,稍微修改下即可)

拖拽原理:

onmousedown(鼠标左键点下),onmousemove(鼠标移动),onmouseup(鼠标松开)三个事件的顺序执行,在移动过程中去获取需要定位的值,然后改变该元素定位的left,top值。

限定边界原理:

做相应的边界判断

直接上代码,代码注释的非常详细:

<template>
	<div>
		<div id="dragBox">
			<div v-for="(item,index) in list" :key="index" class="box1" :style="{left:(index*60 +50)+'px'}"  :id="'a'+index" @click="btnclick(index)">点击{{index}}</div>
		</div>
	</div>
</template>

<script>
	export default{
		data() {
			return{
				list:[1,2,3,4,5],
				isDrag: false
			}
		},
		created() {
		},
		mounted() {
		},
		methods:{
			// 点击元素事件
			btnclick(index) {
				// 打印ID值
				console.log('a'+index)
				// 对多个元素绑定拖拽事件,要先点击,然后才能拖拽(先点击获取元素对象)
				var obj=document.getElementById("a"+index)
				var obox=document.getElementById("dragBox");
				console.log('clientWidth', obox.clientWidth)
				console.log('box.clientWidth', obj.clientWidth)
				// 为每个元素加入拖拽事件
				this.drag(obj,obox)
			},
			drag(box,obox) {
				  var disX
				  var disY
				  var that = this
				  // 鼠标左键按下事件
				  box.onmousedown=function(ev){
				    var oEvent=ev||event
					// clientX,clientY:鼠标点击位置到浏览器可视区域x,y距离
					// offsetLeft,offsetTop:元素距离父级元素的偏移距离
				    disX=oEvent.clientX - box.offsetLeft
				    disY=oEvent.clientY - box.offsetTop
					that.isDrag = true
					console.log('isDrag', that.isDrag)
					console.log('clientX', oEvent.clientX)
					console.log('clientY', oEvent.clientY)
					console.log('offsetLeft', box.offsetLeft)
					console.log('offsetTop', box.offsetTop)
					console.log('disX', disX)
					console.log('disY', disY)
					// 鼠标移动事件
				    document.onmousemove=function(ev){
						// 加入该判断拖拽更流畅
						if (that.isDrag) {
							var oEvent=ev||event
							  // 计算点击元素到父级元素的定位top,left距离
							  var l=oEvent.clientX-disX
							  var t=oEvent.clientY-disY
							  // 设置拖拽边界(限定在浏览器可视区域(空白区域)之内)
							  // 限定左边界
							  // if(l<0){
							  //   l=0
							  // }else if(l>document.documentElement.clientWidth-box.offsetWidth){
							  //   限定右边界
							  //   l=document.documentElement.clientWidth-box.offsetWidth
							  // }
							  // 限定上边界
							  // if(t<0){
							  //   t=0
							  // }else if(t>document.documentElement.clientHeight-box.offsetHeight){
							  //   限定下边界
							  //   t=document.documentElement.clientHeight-box.offsetHeight
							  // }
							  /** 限定拖拽范围,限定拖拽元素在指定的范围内 */
							  // 限定左边界和上边界
							   if(l<0){
								  l=0;
								}
								if(t<0){
								  t=0;
								}
								// 限定右边界的距离(当l=父元素宽-子元素宽时,刚好子元素放在父元素最右边)
							   if(l>obox.clientWidth - box.clientWidth){
								  l=obox.clientWidth - box.clientWidth
								}
								// 限定下边界的距离(当t=父元素高-子元素高时,刚好子元素放在父元素最下边)
								if(t>obox.clientHeight - box.clientHeight){
								   t = obox.clientHeight - box.clientHeight
								}
							  box.style.left=l+'px'
							  box.style.top=t+'px'
							}
						}
				    document.onmouseup=function(){
					  that.isDrag = false
				      document.onmousemove=null
				      document.onmouseup=null //鼠标抬起来后,onmouseup事件本身也没意义了,所以最好清理掉
				    }
				    return false //阻止默认行为,空的div在低版本ff下,第二次拖动手型会变异常
				  }
		}
	}
}	
</script>

<style>
	#dragBox{
		position: relative;
		width:500px;
		height:500px;
		border:1px solid red;
		margin-left:200px;
	}
	.box1{
		width:50px;
		height:50px;
		background:#13CE66;
		/* 一定要设置定位,拖拽就是根据定位实现的 */
		position: absolute;
		top:200px;
	}
</style>