十一.玩转可视化拖拽之插件篇

1,887 阅读5分钟

前言

最近在做的需求,要求将左侧的元素拖拽到右边指定区域,并要求可以对大小位置进行拖拽缩放,刚开始一听到这个需求,刚开始想着直接用插件进行实现,后面针对业务需求自己用原生写了一套,这里记录下使用和封装过程中遇到的问题,希望能对你有点帮助。

插件实现

听到这个需求,脑子里面最快想到的插件是 vuedraggable,使用这个插件即可将左侧的元素克隆到指定画布区域,并且可支持调整顺序等,至于画布内缩放拖动,这里使用另一个插件 vue-drag-resize,使用这个插件即可对元素进行拖拽缩放,初步完成最初的效果。

克隆元素到画布

这里使用的版本是^2.24.3,如果是以前的版本可能有点变化,具体参考 vuedraggable value:你要进行操作的元素,Array类型,推荐使用v-model

group:组名称,只有相同组之间互相拖拽,例如左边盒子要往右边盒子拖拽元素,必须保持两边盒子的组名称一致,才可进行拖拽。 可传递stringObject,如果传递string,即可直接group="componentsGroup",如果是传递Object,他有三个可选属性:namepullput

name 属性即组名称,group="componentsGroup"等价于 :group="{name:'componentsGroup'}"

pull 属性定义从该组件移出去的设置,他有4个可选值true/false/'clone'/functiontrue表示可以被移出,false表示不能被移出,clone表示将克隆一份移出,function可自定义是否能进行移出,通过return true or false 判断是否能被移出。

put 属性定义从该组件移入的设置,true/false/['componentsGroup']/functiontrue,false,function同上,['componentsGroup']可以设置能从其他组件移入过来的组名称,例如:有三个盒子,左、中、右,但是我只想要中间盒子能移入左边盒子,那就在左边盒子设置这个put为:[中间盒子的组名称]

sort:设置当前组是否可以排序。

animation:拖动时的动画时长。

disabled:设置盒子是否能够拖动。

handle:设置只有这个指定的css才能拖动,例如一个盒子我们只想让hover按钮后才能拖动,那就设置handle=".sort",这个.sort就是该按钮的class

ghostClass:设置拖动元素时的class

draggable:设置哪些元素能够拖动,和handle的区别是,handle是设置哪些元素能触发整体拖动,draggable是设置只有哪些元素能够被拖动,例如一个盒子我们只想让hover按钮后才能拖动整个盒子,那就用handle,如果只想按钮能被拖动,那就设置draggable

start:(Function类型) 拖动开始的事件。

end:(Function类型) 拖动结束的事件。

add:(Function类型) 新增时的事件。

remove:(Function类型)移除时的时间。

clone:(Function类型) 设置pull为'clone'后,开始拖动后触发的克隆事件。

....其他属性看官方例子

  • 安装插件

npm install -s vuedraggable
or
yarn add vuedraggable
  • 引入插件(推荐局部引入)

import draggable from "vuedraggable";
components: { draggable}
  • 组件中使用

左侧可拖动元素:

<draggable
  class="component-list"
  :group="{ name: 'componentDrag', pull: 'clone' }"
  :sort="false"
  animation="300"
  draggable=".component-item"
  @end="handleEnd"
  v-model="comList"
  :clone="cloneComponent">
    <div
      v-for="(element, index) in comList"
      :key="index"
      class="component-item"
    >
      <el-icon name="circle-plus-outline" class="icon"></el-icon
      >{{ element.title }}
    </div>
</draggable>


data(){
  return{
    comList: [
        {
          title: "矩形盒子",
          componentName: "dragBox",
          id: "",
          config: {
            w: 150,
            h: 150,
            x: 0,
            y: 0,
          },
        },
        {
          title: "圆形盒子",
          componentName: "dragCircle",
          id: "",
          config: {
            w: 150,
            h: 150,
            x: 0,
            y: 0,
          },
        },
      ],
      currentMove:{},
      drawList:[]
  }
}

methods:{
   //点击左侧拖动克隆当前盒子,记录当前盒子的属性,也可直接记录index
    cloneComponent(e) {
      this.currentMove = {
        id: "box_" + new Date().getTime(),
        ...e,
      };
    },
   
     //拖动盒子到右边画布结束
    handleEnd(e) {
      const { newIndex } = e;
      //这里的drawList是右边画布的list
      this.drawList.push({
         ...this.currentMove
      })
    },
}

右边画布: 主要注意点就是,group设置成和左边名字一样的,然后对应组件的展示用动态组件进行展示。

 <draggable
   group="componentDrag"
   animation="400"
   v-model="drawList">
   <component v-for="com in drawList" :key="com.id" :is="com.componentName"/>
 </draggable>

这样即可实现左边元素克隆到右边画布效果,下一步我们就要实现画布缩放效果。

1.gif

画布移动缩放

这里使用的版本是^1.5.4,如果是以前的版本可能有点变化,具体参考 vue-drag-resize

isDraggable:true /false 是否可拖动。

isResizable:true /false 是否可缩放。

snapToGrid:true /false 是否设置每次移动距离。

w:盒子宽度。

h:盒子高度。

x:盒子left位置。

y:盒子top位置。

z:zIndex层级。

stickSize:缩放图标的大小。

activated:Function类型,单击组件时,组件活跃后触发。

deactivated:Function类型,单击组件外部,组件停止获取触发。

resizing:Function类型,缩放时触发。

resizestop:Function类型,缩放结束后触发。

dagging:Function类型,拖动时触发。

dragstop:Function类型,拖动结束后触发。

  • 安装插件

npm install -s vue-drag-resize
  • 引入插件(推荐局部引入)

import vueDragResize from "vue-drag-resize";
components: { vueDragResize}
  • 组件中使用

画布位置:

 <draggable
     group="componentDrag"
     animation="400"
     v-model="drawList"
     ghostClass="ghost">
   <div
      v-for="(com, index) in drawList"
      :key="index"
      :style="{ width: com.config.w + 'px', height: com.config.h + 'px' }"
    >
      <vue-drag-resize
        :x="parseFloat(com.config.x)"
        :y="parseFloat(com.config.y)"
        :w="parseFloat(com.config.w)"
        :h="parseFloat(com.config.h)"
        @resizestop="handleResizeStop($event, com)"
        @dragstop="handleDragStop($event, com)"
      >
        <component :is="com.componentName" />
      </vue-drag-resize>
    </div>
 </draggable>
 
 methods:{
  //拖动盒子自适应
    handleResizeStop(e, val) {
      val.w = e.width;
      val.h = e.height;
    },

    //拖拽移动停止
    handleDragStop(e, val) {
      val.x = e.left;
      val.t= e.top;
    },
 }

2.gif

实战演练

根据上面总结的,写了一个可视化拖拽的项目,有兴趣可以看看,源码在下方:

777.gif

最后

到这里,通过插件实现已经完成了,后续会写一个原生实现拖拽和缩放的功能,敬请期待; 希望该文章能对你有帮助,如果疑问和建议,可在评论区留言,如果觉得本文写的不错,麻烦点个赞。

在线预览地址:vue-visual-drag
项目地址:vue-visual-drag

其他文章