1. 拖拽器作用
将左侧小组件拖拽到中心区域画布中
2.页面布局及各区域作用
工具
放置一些常用工具,如:撤销,删除,重置等;
左侧小组件列表
遍历渲染全部小组件,用来支持中心画布区域使用;
中心画布区域
承载左侧小组件组装成一个大屏页面,有标尺、标线等,小组件在画布中可随意拖动并支持8点放大缩小,支持鼠标放置小组件上后鼠标右键菜单,功能有撤销上一步、删除该小组件等;
右侧配置项
主要有三个部分,小组件数据源配置,小组件外观属性配置,小组件事件配置;
3.拖拽原理
html5中的支持拖拽的属性「draggable」,draggable设置为"true"时,表示该元素可拖拽;当元素为图片、链接、文本时,draggable属性默认为"true",无需手动设置,除非将上述三种元素禁用拖拽时,需手动设置draggable="false";其它元素需要手动设置draggable="true"来支持该元素的可拖拽;
主要步骤如下:
3.1 将需要拖拽的小组件设置draggable="true"
<component :is="comp.comp" draggable="true" />
// 全部小组件集合
const widgetList = ref>([])
/** 初始化小组件 */
function initWidget() {
widgetList.value.push({
index:1,
name: 'BarChart',
comp: BarChart
}, {
index:2,
name: 'LineChart',
comp: BarChart
})
}
// 初始化小组件列表
initWidget()
3.2 拖拽区域设置拖拽开始事件@dragstart
<!--
在 dragstart 事件处理程序中,我们得到了用户拖动元素的引用。
@dragstart="e => onWidgetDragStart(e, comp)"
-->
<!------------html部分------------->
<div class="w-220px bg-blue-100 pl-40px">
左侧小组件列表
<div
v-for="comp in widgetList"
:key="comp.index"
@dragstart="e => onWidgetDragStart(e, comp)">
{{ comp.name }}
<component :is="comp.comp" draggable="true" />
</div>
</div>
<!------------js部分------------->
// 当前拖拽的小组件
let currentDragWidget = {} as widget
// 当前拖拽小组件的xy坐标
let currentDragWidgetAxis = {} as {x:number, y:number}
/** 开始拖拽小组件 */
function onWidgetDragStart(e: DragEvent, comp: widget) {
currentDragWidget = comp
currentDragWidgetAxis = {x: e.offsetX, y: e.offsetY}
}
3.3 画布区域设置「拖拽结束」@dragover及「放置」事件@drop
<! --
在目标容器的 dragover 事件处理程序中,我们调用 event.preventDefault(),这使它能够接收 drop 事件,否则drop时间不生效。
@dragover="e => e.preventDefault()"
在放置区域的 drop 事件处理程序中,我们将可拖动的元素从原始区域移动到可放置区域。
@drop="onWidgetDrop"
-->
<!------------html部分------------->
<div
class="flex-1 bg-blue-200 flex flex-col"
@dragover="e => e.preventDefault()"
@drop="onWidgetDrop">
中心画布区域
<div
v-for="item in currentCanvasComp"
:key="item.index">
{{ item.name }}
<component :is="item.comp" />
</div>
</div>
<!------------js部分------------->
// 全部小组件集合
const widgetList = ref<Array<widget>>([])
// 当前画布中组件集合
const currentCanvasComp = ref<Array<widgetDrag>>([])
/** 放置拖拽的小组件 */
function onWidgetDrop(e: DragEvent) {
console.log('e=>', e)
currentCanvasComp.value.push({
...currentDragWidget,
x: e.offsetX-currentDragWidgetAxis.x,
y: e.offsetY-currentDragWidgetAxis.y,
active: false,
w: 100,
h: 100
})
}
3.4 画布内拖拽及8点放大缩小
使用vue3-draggable-resizable插件来支持画布内的拖动和缩放。
总结
至此,一个简易的拖拽器核心功能就实现了,主要依赖于html5支持的draggable属性及其事件;