vue-moveable 上手笔记

vue-moveable 上手笔记

1. 简介

moveable 是一个强大的开源web前端交互工具库,github 地址 https://github.com/daybrush/moveable,官方也提供了详尽的 api 文档:文档地址,对于刚接触的新用户可以通过官方提供的 demo 对其有一个直观的了解:demo地址

moveable 非常适合用来开发一些前端交互项目,如可视化的 UI 编辑工具等,它主要有 12 个功能模块:

  • Draggable:拖拽位移
  • Resizable:改变元素尺寸大小
  • Scalable:元素缩放
  • Rotatable:旋转
  • Warpable:透视扭曲变形
  • Pinchable:捏合交互
  • Groupable:分组操作
  • Snapable:捕捉吸附
  • Clippable:裁切
  • Roundable:圆角设置
  • OriginDraggable:原点拖拽
  • Selecto:多选框选

vue-moveable 则是 moveable 的 vue 版本,适合用于 vue 项目中。

2. 基本操作

在 vue 项目中,可以在 data 中定义元素数据用于数据驱动渲染:

data() {
    return {
        // elements
        elements: [{
            uuid: 'aaa',
            width: 0,
            height: 0,
            top: 0,
            left: 0,
            rotate: 0
        }, {
            uuid: 'bbb',
            width: 0,
            height: 0,
            top: 0,
            left: 0,
            rotate: 0
        }, {
            uuid: 'ccc',
            width: 0,
            height: 0,
            top: 0,
            left: 0,
            rotate: 0
        }]
    }
},

而配置参数则可以在 computed 计算属性中动态生成:

computed: {
    moveableConfig() {
        return {
            // 【 draggable 】
            draggable: true,
            throttleDrag: 1, // 步长,默认 0
            throttleDragRotate: 0, // 拖拽角度,默认 0 不限制
            startDragRotate: 0, // 初始拖拽角度
            edgeDraggable: false, // 是否通过拖动边缘线移动,默认 false
            // 【 resizable 】
            resizable: true,
            throttleResize: 1,
            // 【 scalable 】
            // scalable: true,
            throttleScale: 0,
            // 【 rotatable 】
            rotatable: true,
            throttleRotate: 0,
            // 【 snappable 】
            snappable: true, // 是否自动吸附,默认 false
            // snapCenter: true, // 中心吸附
            snapHorizontal: true, // 使用水平参考线
            horizontalGuidelines: [100, 400, 700],
            snapVertical: true, // 使用垂直参考线
            verticalGuidelines: [100, 400, 700],
            bounds: { // 限制外框范围
                left: 0,
                right: 700,
                top: 0,
                bottom: 700
            },
            // innerBounds: [], // 限制内框范围
            snapElement: true,
            snapGap: true,
            snapThreshold: 5, // default 5
            snapDigit: 50,
            isDisplaySnapDigit: true,
            snapDistFormat: distance = > `距离: $ {distance}`,
            // 【 pinchable 】
            pinchable: true, // ["draggable", "resizable", "scalable", "rotatable"]
            // 【 groupable 】
            // groupable: true,
            // target: [],
			// 【 ... 】
            // 【 others 】
            keepRatio: true, // 保持比例
            className: 'test-control', // 指定控制箱 class
            origin: false, // 原点控制箱是否可见
            zoom: 1, // 控制箱手柄大小
            padding: { // 设置目标边距,以增加可拖动区域
                top: 0,
                right: 0,
                bottom: 0,
                left: 0
            },
            dragArea: false, // 将事件添加到可移动区域,而不是将目标添加到 stopPropagation 的目标 (默认值:false,组中为true)
            // container: '',
            edge: true
        }
    }
}

最后是 template 模板,可以在 <Moveable> 组件上绑定所有 api 文档中的事件,如 api 文档中的 onDrag 事件可以绑定为 @drag

<template>
  <div class="moveable">
    <Moveable
      ref="moveable"
      v-for="element in elements"
      :key="element.uuid"
      class="wrapper"
      v-bind="moveableConfig"
      @dragStart="handleTestMoveableEvent"
      @drag="handleDrag"
      @dragEnd="handleDragEnd"
      @dragGroupStart="handleTestMoveableEvent"
      @dragGroup="handleTestMoveableEvent"
      @dragGroupEnd="handleTestMoveableEvent"
      ...
      ...
      ...
      :style="{
        width: element.width + 'px',
        height: element.height + 'px',
        top: element.top + 'px',
        left: element.left + 'px',
        transform: `rotate(${element.rotate}deg)`
      }"
    >
      <div class="element" :data-uuid="element.uuid">
        <h3>{{element.uuid}}</h3>
        <p>{{JSON.stringify(element)}}</p>
      </div>
    </Moveable>
  </div>
</template>
<style scoped>
.moveable {
  width: 100%;
  height: 100%;
  position: relative;
}
.wrapper {
  position: absolute;
  background-color: #cccccc;
}
.element {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: scroll;
  word-break: break-all;
  text-align: left;
}
</style>

关于数据处理,在 demo 中,可以使用 localStorage 进行缓存

created() {
  this.elements.forEach((element) = > {
    element.left = parseInt(localStorage.getItem('moveable_left_' + element.uuid)) || 0
    element.top = parseInt(localStorage.getItem('moveable_top_' + element.uuid)) || 0
    // ...
    // ...
    // ...
  });
},
methods: {
  /**
   * @name: getElementByTarget
   * @desc: 根据 target 对象获取 element 实例
   */
  getElementByTarget(target) {
    if (target.getElementsByClassName('element').length === 0) { return null }
    const uuid = target.getElementsByClassName('element')[0].dataset.uuid
    const element = this.elements.find((element) = > { return element.uuid === uuid })
    return element
  },
  /**
   * @name: handleDrag
   */
  handleDrag({ target, left, top }) {
    console.log('onDrag')
    const element = this.getElementByTarget(target)
    if (!element) { return }
    // 基础数据处理
    const newTop = Math.round(top);
    const newLeft = Math.round(left);
    // 设置 data 数据
    element.top = newTop
    element.left = newLeft
    // 存储数据到缓存
    localStorage.setItem('moveable_top_' + element.uuid, element.top);
    localStorage.setItem('moveable_left_' + element.uuid, element.left);
  }
  // ...
  // ...
  // ...
}

3. 常用参数

3.1 开关参数

moveable 中,各个功能模块需要通过开关参数进行启用或禁用,如:

draggable: true,
resizable: true,
scalable: true,
rotatable: true,
snappable: true,
pinchable: true,
groupable: true,
...

3.2 全局参数

keepRatio: true, // 保持比例
className: 'test-control', // 指定控制箱 class
origin: false, // 原点控制箱是否可见
zoom: 1, // 控制箱手柄大小
padding: { // 设置目标边距,以增加可拖动区域
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
}

3.3 draggable

draggable: true,
throttleDrag: 1, // 步长,默认 0
throttleDragRotate: 0, // 拖拽角度,默认 0 不限制
startDragRotate: 0, // 初始拖拽角度
edgeDraggable: false, // 是否通过拖动边缘线移动,默认 false

3.4 snappable

snappable: true, // 是否自动吸附,默认 false
// snapCenter: true, // 中心吸附
snapHorizontal: true, // 使用水平参考线
horizontalGuidelines: [100, 400, 700],
snapVertical: true, // 使用垂直参考线
verticalGuidelines: [100, 400, 700],
bounds: {
    left: 0,
    right: 700,
    top: 0,
    bottom: 700
}, // 限制外框范围
// innerBounds: [], // 限制内框范围,格式同 bounds
snapElement: true,
snapGap: true,
snapThreshold: 5, // default 5
snapDigit: 50,
isDisplaySnapDigit: true,
snapDistFormat: distance = > `距离: $ { distance }`

3.5 Groupable

当使用分组时,需要设置 targets 参数为数组 Array<HTMLElement | SVGElement>,并且事件也要进行相应转换,如 dragStart => dragGroupStartpinchStart => pinchGroupStart

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
vue-moveable 上手笔记
moveable 是一个强大的开源web前端交互工具库,github 地址 https://github.com/daybrush/moveable,官方也提供...
<<上一篇
下一篇>>