最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • react中拖动元素原生实现

    正文概述 掘金(少冰)   2021-02-20   754

    react中拖动元素原生实现

    mousedown,mousemove,mouseup实现拖拽

    在日常打码中,有可能会遇到通过用户鼠标来移动目标物体,就像上图所示。 在查阅相关博客后。我的思路是通过鼠标按下的位置和移动位置的差值,得到物体应该移动的距离。

      let lastPositionX,lastPositionY,nowPostionX,nowPostionY
      dragElement.onmousedown=function(){  
    	lastPositionX = event.clentX ;
      	lastPositionY = event.clentY ;
        
      }
      dragElement.onmousemove=function(){
      
        nowPositionX = event.clentX ;
        nowPositionY = event.clentY ;
        // 物体应该移动的横向距离 
        let moveeX = nowPostionX - lastPostionX
        // 物体应该移动的纵向距离
        let moveY = nowPostionY - lastPostionY
        /*
           得到物体应该移动的距离后我们应该设置物体的位置
        */
      }
      
    

    react中拖动元素原生实现

    由于鼠标在物体内,但设置物体距离是设置物体的边到窗口边缘的距离。我们知道鼠标在物体内的相对位置应该是一直保持不变的,因为onmousedown时确定相对距离,所以求出上图中的x,y后每次鼠标移动时可以通过相对位置确定物体的位置。

    	//onmousedown时确定相对距离
       x = event.clientX - drag.offsetLeft;
       y = event.clientY - drag.offsetTop;
    

    通过这个方法,我们就不关心物体应该移动的位置,而是关心物体相对于鼠标的位置。那么物体应该设置物体

    drag.style.left = event.clientX - x
    //把 x = event.clientX - drag.offsetLeft代入上式得:
    drag.style.left = drag.offsetLeft + event.clientX(now) - event.clientX(last)
    

    这不就是我们想要的吗?通过相对位置 event.clientX(now) - event.clientX(last)得到drag元素的位置。 还有一些要注意的事情是,如果鼠标移动的速度过快,有可能跑出元素造成中断移动,所以不能在drag上面注册onmousemove和onmouseup,应该在整个html上。另外注册过的事件可以在结束后清除节省内存。 附上html完整代码:

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title></title>
    	</head>
    	<body style="background-color: gray;">
    		<div draggable="true" id="drag" style="background-color: pink; width: 200px;height: 200px;position: absolute;"></div>
    	</body>
    	<script type="text/javascript">
    		var drag = document.getElementById('drag'); 
    		drag.onmousedown = function(event) {
    			var event = event || window.event; //兼容IE浏览器
    			var x = event.clientX - drag.offsetLeft;
    			var y = event.clientY - drag.offsetTop;
    			if (typeof drag.setCapture !== 'undefined') {
    				drag.setCapture();
    			}
    			document.onmousemove = function(event) {
    				event.preventDefault()
    				var event = event || window.event;
    				var moveX = event.clientX - x;
    				var moveY = event.clientY - y;
    				if (moveX < 0) {
    					moveX = 0
    				} else if (moveX > window.innerWidth - drag.offsetWidth) {
    					moveX = window.innerWidth - drag.offsetWidth
    				}
    				if (moveY < 0) {
    					moveY = 0
    				} else if (moveY > window.innerHeight - drag.offsetHeight) {
    					moveY = window.innerHeight - drag.offsetHeight
    				}
    				drag.style.left = moveX + 'px';
    				drag.style.top = moveY + 'px'
    			}
    			document.onmouseup = function(event) {
    				// 多次点击会注册多次事件造成内存泄漏
    				document.onmousemove = null;
    				document.onmouseup = null;
    				//修复低版本ie bug  
    				if (typeof drag.releaseCapture != 'undefined') {
    					drag.releaseCapture();
    				}
    			}
    		}
    	</script>
    </html>
    
    
    

    在react中,要实现元素的拖拽要拿到dom元素才行,所以我们利用React.CreateRef来创建一个钩子和元素建立联系。

      dragElementRef = React.createRef('dragEle');
     	//操作ref实现拖动效果
      const drag = this.dragElementRef.current
      //下面的代码和html代码一样
      drag.onmousedown = function(event) {
    			var event = event || window.event; //兼容IE浏览器
    			var x = event.clientX - drag.offsetLeft;
    			var y = event.clientY - drag.offsetTop;
    			if (typeof drag.setCapture !== 'undefined') {
    				drag.setCapture();
    			}
    			document.onmousemove = function(event) {
    				event.preventDefault()
    				var event = event || window.event;
    				var moveX = event.clientX - x;
    				var moveY = event.clientY - y;
    				if (moveX < 0) {
    					moveX = 0
    				} else if (moveX > window.innerWidth - drag.offsetWidth) {
    					moveX = window.innerWidth - drag.offsetWidth
    				}
    				if (moveY < 0) {
    					moveY = 0
    				} else if (moveY > window.innerHeight - drag.offsetHeight) {
    					moveY = window.innerHeight - drag.offsetHeight
    				}
    				drag.style.left = moveX + 'px';
    				drag.style.top = moveY + 'px'
    			}
    			document.onmouseup = function(event) {
    				// 多次点击会注册多次事件造成内存泄漏
    				document.onmousemove = null;
    				document.onmouseup = null;
    				//修复低版本ie bug  
    				if (typeof drag.releaseCapture != 'undefined') {
    					drag.releaseCapture();
    				}
    			}
    		}
      
      
      //render函数返回
      <div className={styles.xxx} ref={this.dragElementRef} draggable="true" >
    

    dragstart drag dragend实现拖拽

    dragstart drag dragend的方式和mouse的相似,它提供了拖拽和拖放的一些API,拖放是指拖拽后将要放下的位置。 当鼠标点中元素并且开始移动时,就会触发dragstart事件(类比mousedown) 拖拽过程中会持续不断地触发drag事件(类比mousemove) 松开鼠标取消拖拽时就会触发dragend事件(类比mouseup)

    当拖拽的元素拖到一个目标元素上时,目标元素会触发以下事件,这里是目标元素的事件而不是被拖拽元素。

    事件名称是 dragenter dragover dragleave drop

    拖拽元素到目标上,就会触发dragenter事件(类比mouseover)

    如果在mousemove事件中preventDefault()后将监听不到被拖拽元素的drag事件,因为阻止了拖拽的默认行为。

    当拖动元素在目标元素中,就会持续触发dragover事件

    离开目标元素,触发dragleave事件(类比mouseout)

    若拖放元素到了目标元素中(在目标元素中松开鼠标),就会触发drop事件而不会触发dragleave事件 react中拖动元素原生实现

    <div draggable="true" id="drag2" style="background-color: yellow; width: 200px;height: 200px;position: absolute; margin-left: 250px;"></div>
    
    drag.ondragstart = function(event) {
    			var e = event || window.event
    			console.log('开始拖拽');
    		}
    		drag.ondrag = function() {
    			console.log('拖拽中');
    		}
    		drag.ondragend = function() {
    			console.log('拖拽结束')
    		}
    
    
    		const target = document.getElementById("drag2")
    		target.ondragenter = function() {
    			console.log('进入目标元素')
    		}
    		target.ondragover = function(event) {
    			var event = event || window.event;
    			console.log('在目标元素中拖拽');
    			event.preventDefault()
    		}
    		target.ondragleave = function() {
    			console.log('拖放离开目标元素')
    		}
    		target.ondrop = function(event) {
    			console.log('拖放');
    			var e = event || window.event;
    
    		}
    

    拖拽过程中元素的交互,当拖拽元素碰到另一个元素时,可以通过event.dataTransfer这一个中间变量存诗句和取数据,就像localstorage那样。localstorage和datatransfer的区别是localstorage存在于磁盘中而dataTransfer存在于内存,后者的速度更快

    e.dataTransfer.setData('text',e.target.id);类似于localstorage.setItem('text',e.target.id)

    e.dataTransfer.getData('text',e.target.id);类似于localstorage.getItem('text',e.target.id)

    下面这个例子实现把一个元素放入另一个元素里面,通过dataTransfer,比起原先的代码值增加了两行。 react中拖动元素原生实现

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title></title>
    	</head>
    	<body style="background-color: gray;">
    		<div draggable="true" id="drag" style="background-color: pink; width: 200px;height: 200px;position: absolute;"></div>
    		<div draggable="true" id="drag2" style="background-color: yellow; width: 200px;height: 200px;position: absolute; margin-left: 250px;"></div>
    	</body>
    	<script type="text/javascript">
    		var drag = document.getElementById('drag');
    		drag.ondragstart = function(event) {
    			var e = event || window.event
    			console.log('开始拖拽');
    			e.dataTransfer.setData('text',e.target.id); //增加
    		}
    		drag.ondrag = function() {
    			console.log('拖拽中');
    		}
    		drag.ondragend = function() {
    			console.log('拖拽结束')
    		}
    
    
    		const target = document.getElementById("drag2")
    		target.ondragenter = function() {
    			console.log('进入目标元素')
    		}
    		target.ondragover = function(event) {
    			var event = event || window.event;
    			console.log('在目标元素中拖拽');
    			event.preventDefault()
    		}
    		target.ondragleave = function() {
    			console.log('拖放离开目标元素')
    		}
    		target.ondrop = function(event) {
    			console.log('拖放');
    			var e = event || window.event;
    			var data = e.dataTransfer.getData('text');
    			e.target.appendChild(document.getElementById(data));//增加
    		}
    	</script>
    </html>
    
    

    在 dataTransfer还有一些重要的api,用于规定拖拽元素的行为。

    dropEffect

    dropEffect属性值为字符串,表示被拖动元素可以执行哪一种放置行为

    要使用这个属性,必须在dragenter事件处理函数中设置

    none 不能把元素拖放至此(除文本框外全部元素的默认值)

    move 移动到目标

    copy 复制到目标

    link 目标打开拖动元素(拖动元素必须是链接并有URL)

    effectAllowed

    effectAllowed属性值也是字符串,表示允许拖动元素哪种dropEffect

    要使用这个属性,必须在dragst事件处理函数中设置

    uninitialized 没有设置任何拖放行为

    none 不能由任何行为

    copy 仅允许dropEffect值为copy

    link 仅允许dropEffect值为link

    move 仅允许dropEffect值为move

    copyLink 允许dropEffect值为copy和link

    copyMove 允许dropEffect值为copy和move

    linkMove 允许dropEffect值为link和move

    all 允许任意dropEffect

    参考链接:https://blog.csdn.net/weixin_41910848/article/details/82218243


    起源地下载网 » react中拖动元素原生实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元