一、简介
在 PPTist 项目中,画布是指幻灯片编辑区域的主要工作区,具体包括:
- 基础尺寸
- 主要功能:显示和编辑幻灯片、元素拖拽和缩放等、网格线和标尺对齐、元素的选择和多选
- 相关状态:缩放比例、画布能否被拖拽、网格线尺寸等
- 主要操作:缩放、平移、显示网格线标尺等
- 组成部分:背景层、内容层、工具层
- 画布的特点:
响应式:自适应窗口大小、保持宽高比例、支持缩放适配
交互性:支持拖拽移动、支持元素选择、支持快捷键操作
辅助功能:网格对齐、标尺显示、智能参考线
二、基础属性
画布的定义在src/store/main.ts文件,看一下接口定义,包含各个部分的编辑状态、选中状态等等
ts
// 主状态接口定义
export interface MainState {
activeElementIdList: string[] // 被选中的元素ID集合
handleElementId: string // 正在操作的元素ID(如调整大小、旋转等)
activeGroupElementId: string // 组合元素中被选中的子元素ID
hiddenElementIdList: string[] // 被隐藏的元素ID集合
canvasPercentage: number // 画布可视区域百分比
canvasScale: number // 画布缩放比例(基于宽度1000px)
canvasDragged: boolean // 画布是否被拖拽移动
thumbnailsFocus: boolean // 左侧导航缩略图区域是否聚焦
editorAreaFocus: boolean // 编辑区域是否聚焦
disableHotkeys: boolean // 是否禁用快捷键
gridLineSize: number // 网格线尺寸(0表示不显示网格线)
showRuler: boolean // 是否显示标尺
creatingElement: CreatingElement | null // 正在创建的元素信息
creatingCustomShape: boolean // 是否正在绘制自定义形状
availableFonts: typeof SYS_FONTS // 当前环境可用的字体列表
toolbarState: ToolbarStates // 右侧工具栏状态
clipingImageElementId: string // 当前正在裁剪的图片ID
isScaling: boolean // 是否正在进行元素缩放
richTextAttrs: TextAttrs // 富文本编辑器属性
selectedTableCells: string[] // 选中的表格单元格
selectedSlidesIndex: number[] // 当前选中的页面索引集合
dialogForExport: DialogForExportTypes // 导出对话框类型
databaseId: string // 当前应用的indexedDB数据库ID 随机数
textFormatPainter: TextFormatPainter | null // 文字格式刷
shapeFormatPainter: ShapeFormatPainter | null // 形状格式刷
showSelectPanel: boolean // 是否显示选择面板
showSearchPanel: boolean // 是否显示查找替换面板
showNotesPanel: boolean // 是否显示批注面板
}
三、计算属性
typescript
// 计算属性
getters: {
// 获取当前选中的元素列表
activeElementList(state) {
const slidesStore = useSlidesStore()
const currentSlide = slidesStore.currentSlide
if (!currentSlide || !currentSlide.elements) return []
return currentSlide.elements.filter(element => state.activeElementIdList.includes(element.id))
},
// 获取当前操作的元素
handleElement(state) {
const slidesStore = useSlidesStore()
const currentSlide = slidesStore.currentSlide
if (!currentSlide || !currentSlide.elements) return null
return currentSlide.elements.find(element => state.handleElementId === element.id) || null
},
},
四、方法
action
的定义还挺多的,但是里面的实现都比较简单,都是设置状态的值。大家肯定看一眼就明白啦
五、使用
画布状态都在哪里使用,这是一个关键的问题,以后我们在开发新功能的时候,需要知道什么时候要调用这里面的方法。
我们以 setCanvasPercentage
方法为例,这个方法是用来改变画布的缩放的百分比的,在 src/hooks/useScaleCanvas.ts 中使用
typescript
/**
* 缩放画布百分比
* @param command 缩放命令:放大、缩小
*/
const scaleCanvas = (command: '+' | '-') => {
let percentage = canvasPercentage.value
const step = 5
const max = 200
const min = 30
if (command === '+' && percentage <= max) percentage += step
if (command === '-' && percentage >= min) percentage -= step
mainStore.setCanvasPercentage(percentage)
}
/**
* 设置画布缩放比例
* 但不是直接设置该值,而是通过设置画布可视区域百分比来动态计算
* @param value 目标画布缩放比例
*/
const setCanvasScalePercentage = (value: number) => {
const percentage = Math.round(value / canvasScale.value * canvasPercentage.value) / 100
mainStore.setCanvasPercentage(percentage)
}
/**
* 重置画布尺寸和位置
*/
const resetCanvas = () => {
mainStore.setCanvasPercentage(90)
if (canvasDragged) mainStore.setCanvasDragged(false)
}
设置完了之后呢,canvasPercentage
这个属性在哪里使用呢?
是在 src/views/Editor/Canvas/hooks/useViewportSize.ts 这个文件中
typescript
// 可视区域缩放或比例变化时,重置/更新可视区域的位置
watch(canvasPercentage, setViewportPosition)
监听到这个属性变化之后,会计算出画布的位置,然后执行
typescript
// 画布可视区域位置和大小的样式
const viewportStyles = computed(() => ({
width: VIEWPORT_SIZE,
height: VIEWPORT_SIZE * viewportRatio.value,
left: viewportLeft.value,
top: viewportTop.value,
}))
viewportStyles
这个属性又在 src/views/Editor/Canvas/index.vue 文件中使用
html
<div
class="viewport-wrapper"
:style="{
width: viewportStyles.width * canvasScale + 'px',
height: viewportStyles.height * canvasScale + 'px',
left: viewportStyles.left + 'px',
top: viewportStyles.top + 'px',
}"
>
viewport-wrapper
这个元素我们看一下是谁,就是这个编辑区域
可以看出,项目的源码分工还是很细的
如果我们要在编辑区域增加一个新的属性,就需要把属性定义到src/store/main.ts 文件中,然后通过 src/hooks/useXXX.ts 文件进行修改,并且导出模版中需要使用的属性,然后在模版中使用。