往期知识点整理
- 【HarmonyOS 鸿蒙实战开发】NavDestination弹窗
- 【HarmonyOS 鸿蒙实战开发】全局自定义组件复用实现案例
- 【HarmonyOS 鸿蒙实战开发】在TaskPool线程中操作关系型数据库实现案例
- 【HarmonyOS 鸿蒙实战开发】 发短信案例
- 【HarmonyOS 鸿蒙实战开发】 骨架屏实现案例
- 【HarmonyOS 鸿蒙实战开发】 画笔调色板
- 【HarmonyOS 鸿蒙实战开发】图片编辑实现马赛克效果
- 【HarmonyOS 鸿蒙实战开发】橡皮擦案例
- 持续更新中……
介绍
本示例通过 @ohos.graphics.drawing 库和 blendMode颜色混合 实现了橡皮擦功能,能够根据手指移动轨迹擦除之前绘制的内容,并且可以进行图案的撤销和恢复。
效果图预览
使用说明
- 页面底部左侧展示涂鸦和橡皮擦按钮,点击可以切换选中状态和当前的绘制模式,右侧为线宽列表,点击可以修改绘制时的轨迹宽度。
- 在图片上触摸并拖动手指,可以绘制路径,涂鸦模式时绘制橙色线条,橡皮擦模式时擦除线条。
- 页面顶部按钮默认不可用,进行绘制操作后左侧撤销按钮高亮,点击可以撤销上一步绘制,撤销后未进行绘制时右侧恢复按钮高亮,点击可以恢复上一次撤销。
实现思路
- 使用
NodeContainer
构建绘制区域。
- 定义
NodeController
的子类MyNodeController
,实例化后可以通过将自绘制渲染节点RenderNode
挂载到对应节点容器NodeContainer
上实现自定义绘制。
/**
* NodeController的子类MyNodeController
*/
export class MyNodeController extends NodeController {
private rootNode: FrameNode | null = null; // 根节点
rootRenderNode: RenderNode | null = null; // 从NodeController根节点获取的RenderNode,用于添加和删除新创建的MyRenderNode实例
// MyNodeController实例绑定的NodeContainer创建时触发,创建根节点rootNode并将其挂载至NodeContainer
makeNode(uiContext: UIContext): FrameNode {
this.rootNode = new FrameNode(uiContext);
if (this.rootNode !== null) {
this.rootRenderNode = this.rootNode.getRenderNode();
}
return this.rootNode;
}
// 绑定的NodeContainer布局时触发,获取NodeContainer的宽高
aboutToResize(size: Size): void {
if (this.rootRenderNode !== null) {
// NodeContainer布局完成后设置rootRenderNode的背景透明
this.rootRenderNode.backgroundColor = 0X00000000;
// rootRenderNode的位置从组件NodeContainer的左上角(0,0)坐标开始,大小为NodeContainer的宽高
this.rootRenderNode.frame = {
x: 0,
y: 0,
width: size.width,
height: size.height
};
}
}
// 添加节点
addNode(node: RenderNode): void {
if (this.rootNode === null) {
return;
}
if (this.rootRenderNode !== null) {
this.rootRenderNode.appendChild(node);
}
}
// 清空节点
clearNodes(): void {
if (this.rootNode === null) {
return;
}
if (this.rootRenderNode !== null) {
this.rootRenderNode.clearChildren();
}
}
}
- 创建自定义节点容器组件
NodeContainer
,接收MyNodeController
的实例,组件的宽高为图片加载完成后实际内容区域的宽高,并通过相对容器布局的alignRules
使NodeContainer
与图片内容区域重叠,控制绘制区域。
@Builder
drawingArea() {
Image($r('app.media.palette_picture'))
.width($r('app.string.palette_full_size'))
.objectFit(ImageFit