探讨把一个元素从它所在的div 拖动到另外一个div...

故事背景:css

接到一个新需求,要求用vue搞,主要是拖动实现布局,关键点有:单个组件拖动,一行多列里面的组件拖动,  单个组件能够拖入一行多列里, 单个组件的拖动好实现,关键是把一个组件拖动到另外一个相似于表格里面,并且有的状况下还须要限制拖动只能在水平方向,本身搜集资料, 实验,终于搞出来了。

原理上主要分为两类:
HTML5自带的拖放api,可用的库有 : Vue.Draggable
使用js 监听鼠标的移动位置, 可用的库有: jquery ui
使用point-event: none(下面会详细说明)
各自缺点
H5拖动的缺点:不能限制在水平 或垂直方向上拖动。html

使用原生js缺点:大量的dom操做,代码复杂(jquery ui 封装的比较好了,可直接用)vue

可是问题来了,此次的需求是把基于jquery ui 的拖动 用 vue 重构,那么用vue.draggable吧, 可是需求里正好有一条是要限制在水平方向上拖动,尴尬,用不了。jquery

寻找方案
最开始的尝试:git

[HTML] 纯文本查看 复制代码
?github

<!DOCTYPE html>
<html>
<head>api

<title>vue结合原生js实现拖动</title>

<script src="https://cdn.bootcss.com/vue/2...;></script>
</head>
<body>
<div id="app">
<div class="ctn ctn1">app

<div class="sub sub1" v-for="(site, index) in list1">
  <div class="dragCtn fixed" :style="{ left: X+'px', top: Y+'px'}"
       @mousedown="mousedown(site, $event)"
       @mousemove.prevent='mousemove(site, $event)'
       @mouseup='mouseup(site, $event)'>
    拖动我
  </div>

</div>
</div>dom

<div class="ctn ctn2">wordpress

<div class="sub sub2" v-for="(site, index) in list2"
      @mouseenter='mouseenter(site, $event)'>
  <div class="dragCtn">
    {{ index }} : {{ site.name }}
  </div>

</div>
</div>

</div>

<script>
new Vue({
el: '#app',
data: {

list1: [{name:1, index:0}],
list2: [{name:'a', index:0}, {name:'b', index:1}, {name:'c', index: 2}, {name:'d', index: 3}],
vm:'',
sb_bkx: 0,
sb_bky: 0,
is_moving: false,
X: 0,
Y: 0

},
methods: {

mousedown: function (site, event) {
    var startx=event.x;
    var starty=event.y;
    this.sb_bkx=startx - event.target.offsetLeft;
    this.sb_bky=starty - event.target.offsetTop;
    this.is_moving = true;
},
mousemove: function (site, event) {
    var endx=event.x - this.sb_bkx;
      var endy=event.y - this.sb_bky;
      var _this = this
      if(this.is_moving){
        this.X = endx;
        this.Y = endy;
  }
},
mouseup: function (e) {
  this.is_moving = false;
},
mouseenter: function (){
  console.log('鼠标进入')
}

}
})
</script>

<style>

.ctn{
    line-height: 50px;
    cursor: pointer;
    font-size: 20px;
    text-align: center;
    float: left;
}
.sub:hover{
    background: #e6dcdc;
    color: white;
    width: 100px;
}
.ctn1{
    border: 1px solid green;
    width: 100px;
}
.ctn2{
    border: 1px solid black;
    width: 100px;
    margin-left: 50px;
}
.fixed{
  width: 100px;
  position: fixed;
  background: red;
  left: 0;
  top: 0;
  cursor: move;
}

</style>
</body>
</html>

就这样实现了基本的拖动,可是在拖动的时候,就不能触 mouseenter 事件了,并且鼠标必须拖动的很慢,移动快一点,拖动的div就跟不上了,这一点到如今还困惑,但愿各位大侠指点。而后在网上找了不少资料,类库,可是不能彻底符合个人需求,因而准备本身写了;

首先是给组件添加mousedown事件,而后mousemove的时候 监听鼠标的位置,再赋值给组件,实现拖动,可是当组件拖动进入另外一个元素的时候,没法监听mouseenter, 后来想的办法是给正在拖动的组件加上 point-event:none 属性,就是消除原有的鼠标事件,就能够触发其余组件的mouerenter事件了,point-event 属性的具体用法 能够参考这里:

www.zhangxinxu.com/wordpress/2…

由于拖动是用原生js写的,因此能够限制在水平方向拖动,再加上能够触发mouseenter事件,就正好实现的个人需求。

伪代码以下:

[JavaScript] 纯文本查看 复制代码
?

mousedown: function (event, site) {

document.onmousemove=function (ev) {          
             // 移动的时候给元素增长 point-event:none 属性           
             ...        
      }        
       document.onmouseup=function (ev) {
             // up的时候 要移除point-event属性
             ...         
       }

}

可是后来上面要求,要兼容ie10,因为 point-event:none 是H5的属性,因而我赶忙去看看兼容性, 可怕的事发生了,point-event 属性只兼容到 ie11,完蛋!

     再想其余办法吧,没了思路,老版本的拖动是基于 jquery ui  的 ,因而去看了 jquery ui 的源码,看看它的拖动是怎么实现的。

jquery ui 拖动实现原理

不熟悉 jquery ui 的拖动方法的能够先看下  这里   

  看下面这段代码:

[JavaScript] 纯文本查看 复制代码
?

$(function() {

$( "#draggable" ).draggable();
$( "#droppable" ).droppable({
  drop: function( event, ui ) {
    $( this ).html( "Dropped!" );
  }
});

});

以前的关键问题就是怎么判断拖动的元素  $( "#draggable" )  在何时 进入了能够放置的区域      $( "#droppable" ) 的,看了源码,它的实现方式 简单来讲就是拖动  $( "#draggable" )  的时候监听 鼠标的位置, 同时获取  $( "#droppable" )   的区域位置信息,只要鼠标进入该区域,就触发。

  顺着这个思路,作了实验 能够知足本身的需求 good !

  demo的实现效果以下:

代码地址: https://github.com/YalongYan/...

拖动布局的实现方式应该还有更好的,欢迎你们提出更好的实现方式。更多技术资讯可关注:gzitcast

相关文章
相关标签/搜索