vue、HTML5拖拽实现;包含鼠标监听实现 HTML5实现两种

37 篇文章 0 订阅
5 篇文章 0 订阅

效果如图

看一下缩放代码
在这里插入图片描述

1、通过自定义指令 + 鼠标事件实现

 
    // 自定义指令
    directives:{
        /* 
			指令钩子函数会被传入以下参数:
			el:指令所绑定的元素,可以用来直接操作 DOM 。
			binding:一个对象,包含以下属性:
					name:指令名,不包括 v- 前缀。
					value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
					oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
					expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
					arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
					modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
			vnode: Vue编译生成的虚拟节点。移步 VNode API 来了解更多详情。
			oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。 
		*/
        drag(el,binding,vnode) {   
            let that = vnode.context   
            let canDrag = binding.value.isCanDrag && that.prillingConfig.isCanDrag//是否可拖拽
            let currentKey = binding.value.index//当前操作的数组下标
            let  leftB=''
            let topB='' 
            el.onmousedown = function (e) {    
                if(!canDrag)return; //该字段判断是否显示 
                e.preventDefault() 
                // clientX、clientY 点击位置距离当前body可视区域的x,y坐标  
                let thex = e.clientX
                let they = e.clientY 
                //获取该拖拽容器的宽高  此处父级便是容器 则直接去赋值的宽高
                let dom = document.getElementById('dragDiv'+that.currentId) 
                let ph = dom.offsetHeight// 父元素高度 
                let pw = dom.offsetWidth  // 父元素宽度 
                
				//在鼠标点击之后  监听鼠标移动事件 并随之修改其定位信息
                document.onmousemove = function (e) {  
                    if(!canDrag)return; 
                    //鼠标现在距离视口宽度的距离  - 刚才距离视口宽度的距离  =  相对刚才的偏移 
                    let movx = e.clientX - thex
                    let movy = e.clientY - they 
                    /**
                     * 元素本身高度和距离顶端的高度和
                     * el.offsetTop  当前元素相对父级的top 
                     * el.offsetHeight  当前元素高度
                     */
                    let totalH = el.offsetTop + movy + el.offsetHeight 
                    // 元素本身宽度和距离左面的宽度和
                    
                    //           距离父组件左侧   鼠标偏移  元素宽度
                    let totalW = el.offsetLeft + movx + el.offsetWidth
                    // 限制移动范围
                    if (el.offsetHeight < totalH/* && totalH < ph*/) {
                        // el.style.top = (el.offsetTop + movy) + 'px'
                        // console.log((el.offsetTop + movy)/ph*100 )
                        el.style.top = (el.offsetTop + movy)/ph*100 + '%'
                        topB = (el.offsetTop + movy)/ph*100
                    } 
                    // 限制移动范围
                    // 元素小于屏幕宽度,且没有超越边界
                    // console.log("元素右侧距离左侧距离:",totalW,'元素宽度:',el.offsetWidth,'父元素宽度',pw) 
                    if (el.offsetWidth < totalW && totalW < pw) {
                        // el.style.left = (el.offsetLeft + movx) + 'px'
                        el.style.left = (el.offsetLeft + movx)/pw*100 + '%'
                        leftB = ((el.offsetLeft + movx)/pw*100 ).toFixed(2) < 0 ? 0 : ((el.offsetLeft + movx)/pw*100 ).toFixed(2)
                    } else if (el.offsetWidth > pw) { // 标签的宽度大于屏幕宽度
                        if (totalW > 30 && totalW < (pw + el.offsetWidth - 30)) {
                            // el.style.left = (el.offsetLeft + movx) + 'px'
                            el.style.left = (el.offsetLeft + movx)/pw*100 + '%'
                            leftB =  ((el.offsetLeft + movx)/pw*100).toFixed(2) < 0 ? 0 : ((el.offsetLeft + movx)/pw*100).toFixed(2)
                        }
                    } 

                    thex = e.clientX
                    they = e.clientY  
                    //利用防抖赋值给需要绑定的字段
                    if(window.FunMove){clearTimeout(window.FunMove)}
                    window.FunMove = setTimeout(()=>{
                        try{ 
                            that.JsonData[currentKey].style.leftB = leftB || that.JsonData[currentKey].style.leftB
                            that.JsonData[currentKey].style.topB= topB || that.JsonData[currentKey].style.topB
                            console.log("修改")
                        }catch(Err){}
                        window.FunMove = false
                    },50)
                }
                //在鼠标抬起时  解除事件绑定
                document.onmouseup = function (e) { 
                    document.onmousemove = null; 
                    document.onmouseup = null;
                }
            }
        }
    }, 

html代码部分
在这里插入图片描述







2通过HTML5中drag实现

HTML代码部分

//绑定值目标元素
@drop="drop" 
//绑定至被拖拽元素
    @dragstart.stop="dragstart" //开始拖拽
    @drag.stop='draging' //拖拽中
    @dragend.stop="dragend"//拖拽结束
    :draggable="prillingConfig.isCanDrag" //判断是否可拖拽 Boolean
        // 拖拽 start
            dragstart (ev) { //拖拽开始事件
                ev.target.parentNode.parentNode.parentNode 
                ev.dataTransfer.setData('Text', ev.target.id)
                // 开始点击时 鼠标在元素中的定位  保存再来后续计算偏移
                this.offsetX = ev.offsetX
                this.offsetY = ev.offsetY 
            },
            // 拖拽中
            draging (e) {  
                let that = this
                let x = e.clientX
                let y = e.clientY
                
                // drag事件最后一刻,无法读取鼠标的坐标,pageX和pageY都变为0
                if (x === 0 && y === 0) {
                    return // 不处理拖动最后一刻X和Y都为0的情形
                }
                x -= this.offsetX
                y -= this.offsetY
 
                //获取被拖拽元素DOM  因可能拖拽的是目标子元素 设置top left 无效 所以要获取到 需要被拖拽的元素 给其赋值left 及 right
                let dom = document.getElementById(that.getParent(e.target,'a_particle'))  

                // 父级元素 距离 视口 左侧及顶部的距离
                let parent = document.getElementById('dragDiv'+that.currentId) 
                let domToTop = parent.getBoundingClientRect().top   
                let domToLeft = parent.getBoundingClientRect().left   
                let ph = parent.offsetHeight// 父元素高度 
                let pw = parent.offsetWidth  // 父元素宽度

                let left = 0
                let top = 0
                //判断取值是% || px
                if(dom.style.left && dom.style.left.indexOf('%')!=-1){ 
                    left = (x - domToLeft)/pw*100+'%'
                }else{
                    left = x -domToLeft + 'px'
                }
                if(dom.style.top && dom.style.top.indexOf('%')!=-1){
                    top = (y-domToTop)/ph*100+'%'
                }else{
                    top = y-domToTop + 'px' 
                } 

                dom.style.left = left
                dom.style.top = top
            },
            drop (ev) {
                console.log('drop拖放事件,绑定可拖放区域', ev) 
                let target = document.getElementById(ev.dataTransfer.getData('Text'))
                ev.target.appendChild(target)
                ev.preventDefault()
            },
            dragend (event) {
                event.dataTransfer.clearData()
            }, 
	        /**
	         * @description: 根据ID 寻找dom 如果未发现 继续往父级搜索 
	         * @param {Object} dom  DOM对象
	         * @param {string} id  需要查找的ID
	         */ 
            getParent(dom,id){  
                if(dom.id && dom.id.indexOf(id)!=-1){
                    return dom.id
                }else{
                    return this.getParent(dom.parentNode,id)
                } 
            },
        //拖拽 end 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Web_Lys

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值