低代码开源源码学习-04-Editor 编辑器源码实现
2022年9月3日大约 5 分钟
整体结构
页面整体样式如下:
代码分析
整体结构
我们逐个简单看一下
Toolbar
最上方的工具栏
画布大小
*
import { mapState } from 'vuex'
export default {
components: { },
data() {
return {
scale: 100,
}
},
computed: mapState([
'canvasStyleData',
]),
created() {
this.scale = this.canvasStyleData.scale
},
methods: {
},
}
这里可以改变画布的大小,还有一个 scale 缩放比例,为了简单,我们暂时固定为 100。
ComponentList
左侧的组件列表
import componentList from '@/custom-component/component-list'
export default {
data() {
return {
componentList,
}
},
methods: {
handleDragStart(e) {
e.dataTransfer.setData('index', e.target.dataset.index)
},
},
}
配置
其中 componentList 是一堆关于组件的属性配置。
// 公共样式
export const commonStyle = {
rotate: 0, // 旋转
opacity: 1, // 透明度
}
export const commonAttr = {
animations: [], // 动画
events: {}, // 事件
groupStyle: {}, // 当一个组件成为 Group 的子组件时使用
isLock: false, // 是否锁定组件
collapseName: 'style', // 编辑组件时记录当前使用的是哪个折叠面板,再次回来时恢复上次打开的折叠面板,优化用户体验
}
// 编辑器左侧组件列表
const list = [
{
component: 'VText',
label: '文字',
propValue: '双击编辑文字',
icon: 'wenben',
style: {
width: 200,
height: 28,
fontSize: '',
fontWeight: 400,
lineHeight: '',
letterSpacing: 0,
textAlign: '',
color: '',
},
},
]
// 初始化整个组件样式列表
for (let i = 0, len = list.length; i
handleDrop
handleDrop 对应的是鼠标放下的事件:
handleDrop(e) {
e.preventDefault()
e.stopPropagation()
const index = e.dataTransfer.getData('index')
const rectInfo = this.editor.getBoundingClientRect()
if (index) {
// 深度拷贝
const component = deepCopy(componentList[index])
component.style.top = e.clientY - rectInfo.y
component.style.left = e.clientX - rectInfo.x
// 生成唯一标识
component.id = generateID()
// 根据画面比例修改组件样式比例 https://github.com/woai3c/idrag/issues/91
changeComponentSizeWithScale(component)
this.$store.commit('addComponent', { component })
}
},
根据鼠标按下时对应的组件,深度拷贝后,添加到当前的页面中。
其中 addComponent 在 store/index.js 中
addComponent(state, { component, index }) {
if (index !== undefined) {
state.componentData.splice(index, 0, component)
} else {
state.componentData.push(component)
}
},
vText 组件
简单的文本组件。
= 0 使得双击时聚焦该元素 -->
Editor 编辑器
这个可以理解为画布的真正实现
画布大小
最上方样式指定了画布的大小,可以在 Toolbar 中变化。
Grid 网格线
.grid {
position: absolute;
top: 0;
left: 0;
}
基于 SVG 实现的,感觉比较巧妙。
组件渲染
shape 中是对 componentData 组件数组的渲染。
这个数组就是上面拖拽后变化的。
shape 形状
点击之后,出现的旋转按钮,和 8 个方向按钮。
便于后续实现放大缩小,旋转。
属性列表
curComponent 当前组件
这个属性对象在很多地方会被改变,基于 vuex 的统一管理。
渲染为对应的属性。
VTextAttr
文本的属性示例:
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
export default {
components: { CommonAttr },
computed: {
curComponent() {
return this.$store.state.curComponent
},
},
}
CommonAttr 通用属性
通用属性。
CanvasAttr 画布属性
如果没有选中任何组件,默认显示的是画布属性。
画布属性
参考资料
贡献者
binbin.hou