
#HarmonyOS NEXT体验官# 基于鸿蒙Next的App(创意工坊)解析2:新建绘画文档 原创
在上一篇文章我们介绍了创意工坊的主要功能,以及整体UI的实现。在这篇文章中,会详细介绍如何创建新的绘画文档,并与fabric进行交互。
点击“新建”按钮,会弹出如下图的窗口。
输入文档名,选择尺寸,就可以创建一个带网格的文档,如下图所示:
显示创建文档的窗口,需要使用arkts创建一个组件,代码如下:
代码实现原理
- 组件定义和初始化
:NewDocument组件通过装饰器@Component和@Entry进行定义。它包含了几个状态变量和控制器,包括documentName用于存储文档名称,documentNameController用于控制文本输入,rootPath保存了根路径。
- UI构建
:使用了多种UI组件来构建用户界面:
- Column:作为根布局,包含其他子组件。
- TextInput:用于输入文档名称,包含占位符、光标颜色、背景颜色等属性配置。
- Scroll:用于实现滚动效果,包含一个Column,该列包含多个文档尺寸选择按钮。
- Button:根据文档尺寸生成的按钮,点击按钮时会触发相关逻辑。
- 事件处理
:
- 文本输入框的onChange事件:当用户输入文档名称时,更新documentName状态。
- 按钮的onClick事件:点击文档尺寸按钮时,首先检查文档名称是否为空或已存在。如果为空,则显示提示对话框;如果已存在,则显示提示对话框。如果通过以上检查且newDocumentSelected事件已定义,则调用此事件,并传入文档名、文档路径和文档尺寸。
- 文档目录操作
:
- 使用documentExists函数检查文档是否已存在。
- 使用createDocumentDir函数创建文档目录,并获取其路径。
- 样式设置
:通过链式调用设置了组件的多种样式属性,包括背景颜色、字体颜色、边框等。
通过以上步骤,实现了一个交互式的新建文档窗口,用户可以输入文档名称并选择文档尺寸,点击按钮后会进行相关检查,并通过回调函数传递文档数据进行进一步处理。
当创建文档后,会回调newDocumentSelected事件函数,在这个函数中,会与arkweb交互,也就是调用js代码利用fabric创建文档,代码如下:
实现原理解释
- 面板状态更新
- this.toggleNewPanel():调用此方法来隐藏新建文档面板。
- this.currentDocumentName = documentName 和 this.currentDocumentPath = documentPath:更新当前文档的名称和路径。
- this.newPanelVisibility = Visibility.None 和 this.noDocumentVisibility = Visibility.None:将新建面板和无文档提示的可见性设置为不可见。
- 画布尺寸设置
- this.currentCanvasWidth = documentSize[1] 和 this.currentCanvasHeight = documentSize[2]:设置当前画布的宽度和高度。
- this.controller1.runJavaScript(setCanvasSize("${documentSize[1]}","${documentSize[2]}")):通过执行JavaScript代码来设置画布的尺寸,调用了setCanvasSize函数,并传入宽度和高度。
- 定时器启动与画布数据保存
- if (this.intervalId < 100):检查定时器ID是否小于100,以防止重复启动定时器。
- setInterval(() => {...}, 500):启动一个定时器,每隔500毫秒执行一次内部的匿名函数。
- this.controller1.runJavaScript(getCanvasJSON()):定时获取画布的JSON数据,调用了getCanvasJSON函数。
- .then(data => {...}):当获取到画布的JSON数据后,调用this.saveCanvas(trimQuotes(data))方法保存画布数据,其中trimQuotes函数用于去除数据中的引号。
- 防止定时器重复启动
- this.intervalId = 100:将定时器ID设置为100,确保不会重复启动定时器。
详细流程
- 用户在新建文档窗口输入文档名称并选择文档尺寸。
- 调用newDocumentSelected方法:
- 隐藏新建面板和无文档提示。
- 更新当前文档的名称和路径。
- 设置画布的宽度和高度。
- 通过JavaScript代码设置画布尺寸。
- 如果定时器尚未启动,启动定时器,每隔500毫秒获取画布数据并保存。
这样,用户可以创建一个新文档,并实时获取和保存画布的数据,实现了文档的动态管理和数据持久化。
最后,我们来看一下setCanvasSize函数,这是用js实现的,arkts将文档数据传给setCanvasSize函数,然后创建了一个fabric画布,该函数的代码如下:
实现原理解释
- 尺寸转换
- convertDimensionToPixels(width) 和 convertDimensionToPixels(height):将传入的宽度和高度转换为像素值。
- 初始化画布
- initCanvas(newWidth, newHeight):使用新宽度和高度初始化画布。
- 更新全局变量
- currentCanvasWidth 和 currentCanvasHeight:更新全局变量,存储当前画布的宽度和高度。
- 设置画布尺寸
- canvas.setWidth(newWidth) 和 canvas.setHeight(newHeight):设置画布的实际宽度和高度。
- 裁剪路径(clipPath)处理
- 如果画布没有裁剪路径(canvas.clipPath为空),则创建一个新的fabric.Rect对象作为裁剪路径,并将其设置为画布的clipPath。
- 如果已有裁剪路径,则更新其宽度和高度。
- 添加网格线
- addGridLines(gridSize, smallCellNumber, 'dashed'):调用此函数在画布上添加网格线,参数包括网格尺寸、小网格单元数量和线型(虚线)。
- 重新渲染画布
- canvas.requestRenderAll():请求重新渲染画布,以应用新的尺寸和裁剪路径。
详细流程
- 转换尺寸:首先将传入的宽度和高度转换为像素值,确保画布的尺寸与实际需求匹配。
- 初始化和更新画布:初始化画布并设置新的宽度和高度,同时更新全局变量以记录当前画布尺寸。
- 处理裁剪路径:如果没有裁剪路径,则创建一个新的裁剪路径,并将其设置为画布的clipPath;如果已有裁剪路径,则更新其尺寸。
- 添加网格线:在画布上添加网格线,便于用户进行图形绘制和对齐操作。
- 重新渲染:请求画布重新渲染,以确保所有更改即时生效。
通过以上步骤,setCanvasSize函数能够动态调整画布的尺寸,并确保画布的其他相关属性和视觉元素(如裁剪路径和网格线)同步更新,从而为用户提供一个可调整的绘图环境。
