1. 简介
VUE基于MVVM模式,通过封装、动态配置、滤器和自定义指令等机制,可以实现业务逻辑和UI组件的高度复用;同时,Canvas为浏览器提供了一个能够在其中绘制元素的标记语言,我们可以用Canvas实现一些图形渲染或图像处理的需求。那么如何利用Vue和Canvas进行可拖拽元素的组件库开发呢?
2. 准备工作
实现一个可拖拽的元素,在DOM节点上通过JavaScript添加事件监听,移动物体时需要频繁的进行DOM操作,性能不容乐观。在这里我们采用Canvas绘制的方式,可以有效的减少HTML节点的增加,减少页面Reflo
流。
2.1 安装
使用命令npm i vue-canvas-application可以将其安装到项目依赖中。
npm i vue-canvas-application
2.2 引入
将组件库挂载到main.js里面,代表该库中所有组件在该Vue项目下面可以被使用。
import Vue from 'vue'
import VueCanvasApplication from 'vue-canvas-application'
Vue.use(VueCanvasApplication)
3. 开始使用
这里我们使用VueCanvasApplication的draggable组件实现拖拽效果,我们需要先引入Draggable组件,然后再在需要拖拽的元素节点上注册该组件。
// 引入组件
import { Draggable } from 'vue-canvas-application'
export default {
components: {
// 注册组件
Draggable
}
对于我们需要拖拽的元素节点(比如一个div),我们需要添加一个class,这样我们就能够在注册Draggable的时候调用该class。
<div class="draggable"></div>
在组件中引用,我们可以通过v-model、v-prevent-click、v-force-disable等属性来设置组件的状态。如下所示,当我们拖动组件时会触发drag事件。
<template>
// 组件
<Draggable
v-model="dragging"
v-on:drag="handleDrag">
<template>
// 组件data
export default {
data () {
return {
dragging: false
}
},
methods: {
handleDrag () {
// 处理drag事件
}
}
4. 实现
现在我们已经实现了一个可拖拽的组件,接下来我们要更进一步,将组件移动到Canvas画布上。首先我们要在组件的dom中添加属性来标识段落的位置。
<template>
<Draggable
:style="{ position: 'absolute', top: top + 'px', left: left + 'px' }"
v-model="dragging"
v-on:drag="handleDrag">
</template>
<script>
export default {
data () {
return {
// 添加标识位
top: 0,
left: 0,
dragging: false
}
},
methods: {
handleDrag () {
const canvas = document.getElementById('canvas'); // 获取canvas元素
const ctx = canvas.getContext('2d');
// 清除画布上的元素
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 获取拖拽组件的位置
const rect = this.$el.getBoundingClientRect();
this.top = rect.top
this.left = rect.left
// 绘制拖拽组件
ctx.fillStyle = 'red';
ctx.fillRect(rect.left - 10, rect.top - 10, 30, 30);
}
}
</script>
上述代码表示clearRect()方法会清楚整个canvas画布,然后将canvas上拖拽组件的位置设置到Vue组件实例this.top和this.left中。接下来我们绘制一个30*30的矩形作为拖拽组件。我们可以看到,当拖动组件时,矩形会跟着移动。
如果我们想将组件移动到画布上的其他位置,需要进行重新绘制。在Vue watch或computed中监听this.top和this.left,当其改变时,重新绘制组件。
function createRectangle(top = 0, left = 0) {
const ctx = canvas.getContext('2d');
// 绘制拖拽组件
ctx.fillStyle = 'red';
ctx.fillRect(left - 10, top - 10, 30, 30);
}
export default {
data () {
return {
dragging: false,
top: 0,
left: 0
}
},
watch: {
top: {
handler(newValue) {
// 清除canvas画布上的元素
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制拖拽组件到新的位置
createRectangle(this.top, this.left);
}, deep: true
},
left: {
handler (newValue) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
createRectangle(this.top, this.left);
}, deep: true
}
},
methods: {
handleDrag () {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除canvas画布上的元素
const rect = this.$el.getBoundingClientRect();
this.top = rect.top
this.left = rect.left
createRectangle(this.top, this.left); // 在新的位置重新绘制组件
}
}
上述代码表示canvas画布上的元素都被清除了,然后重新将拖拽组件移动到this.top和this.left指定的位置。当this.top或this.left发生变化时,watch监听它们的变化,生成一个新的矩形并在新的位置绘制它。
5. 结语
本文介绍了如何使用Vue和Canvas开发一个可拖拽的元素组件库。我们可以看到使用Draggable组件与Canvas配合可以实现一个高效的拖拽组件库,并且可以借助Vue的数据监听来适时的更新组件的状态。希望上述内容对学习Vue和Canvas开发有所启迪。