HarmonyOS鸿蒙Next中关于自定义绘制组件Canvas的使用异常
HarmonyOS鸿蒙Next中关于自定义绘制组件Canvas的使用异常 有需求要做一个签名组件,和市场上常用的签名组件功能基本一致,在使用Canvas组件进行绘制等操作的时候发现现阶段无法实现撤销某一笔画的功能。
一笔一笔的签名,可能需要撤销上一笔的签名路径,那么该需求在基于Canvas该怎么实现呢?
1 回复
更多关于HarmonyOS鸿蒙Next中关于自定义绘制组件Canvas的使用异常的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
参考demo如下
DrawCanvas.ets
import DrawInvoker from '../draw/DrawInvoker'
import DrawPath from '../draw/DrawPath'
import { IBrush } from '../draw/IBrush'
import NormalBrush from '../draw/NormalBrush'
import Paint from '../draw/Paint'
@Entry
@Component
export struct DrawCanvas {
@State @Watch('createDraw') isDrawing: boolean = false //标识是否可以绘制
@State unDoDraw: boolean = false; //撤销操作
@State redoDraw: boolean = false; //重做操作
@State drawHeight: number = 0;
@State drawWidth: number = 0;
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
private drawInvoker: DrawInvoker = new DrawInvoker();
private path2Db: Path2D = new Path2D()
private mPaint: Paint = new Paint(); //画笔对象
private mPath: DrawPath = new DrawPath(); //绘制路径
private mBrush: IBrush = new NormalBrush(); //笔触对象
/**
* 默认为黑色
*/
async aboutToAppear() {
this.mPaint = new Paint();
this.mPaint.setStrokeWidth(3);
this.mPaint.setColor(Color.Blue)
this.mBrush = new NormalBrush();
}
/**
* 添加一条绘制路径
* @param path
*/
add(path: DrawPath): void {
this.drawInvoker.add(path);
}
/**
* 撤销上一步
*/
unDo() {
this.drawInvoker.undo();
this.isDrawing = true
}
/**
* 是否可以撤销
*/
canUnDo(): boolean {
return this.drawInvoker.canUndo();
}
createDraw() {
//绘制背景
if (this.isDrawing) {
//从新绘制画板颜色,从而到达重新绘制效果
this.context.fillStyle = '#ffff00'
this.context.fillRect(0, 0, this.context.width, this.context.height);
this.drawInvoker.execute(this.context)
this.isDrawing = false;
}
}
onTouchListener(event: TouchEvent) {
if (event.type === TouchType.Down) {
this.mPath = new DrawPath();
this.mPath.paint = this.mPaint;
console.info('onTouchListener DrawPath == ' + this.mPath.paint.strokeStyle)
this.mPath.path = new Path2D();
this.mBrush.down(this.mPath.path, event.touches[0].x, event.touches[0].y)
}
if (event.type === TouchType.Up) {
this.mBrush.up(this.mPath.path, event.touches[0].x, event.touches[0].y)
//添加路径
this.add(this.mPath);
this.isDrawing = true;
this.redoDraw = false;
this.unDoDraw = true;
}
if (event.type === TouchType.Move) {
this.mBrush.move(this.mPath.path, event.touches[0].x, event.touches[0].y)
}
}
/**
* 正常笔触
*/
drawBrushNormal() {
this.mBrush = new NormalBrush();
}
/**
* 撤销操作
*/
drawOperateUndo() {
this.unDo();
if (!this.canUnDo()) {
this.unDoDraw = false
}
this.redoDraw = true;
}
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#ffff00')
.onTouch(this.onTouchListener.bind(this))
.width('100%')
.layoutWeight(1)
Column() {
Row() {
Button('撤销', { type: ButtonType.Normal, stateEffect: true })
.borderRadius(8)
.backgroundColor(0x317aff)
.height(60)
.margin({ right: 4 })
.enabled(this.unDoDraw)
.layoutWeight(1)
.onClick(async () => {
this.drawOperateUndo();
})
}
.width('90%')
.margin({ top: 4, bottom: 8 })
.alignItems(VerticalAlign.Center)
}
}
.width('100%')
.height('100%')
}
}
entry-》src-》main-》ets-》draw文件夹 DrawInvoker.ets
import List from '@ohos.util.List';
import DrawPath from './DrawPath';
export default class DrawInvoker {
//绘制列表
private drawPathList:List<DrawPath> = new List<DrawPath>();
//重做列表
private redoList:List<DrawPath> = new List<DrawPath>();
/**
* 添加绘制路径
*/
add(command:DrawPath):void{
this.redoList.clear();
this.drawPathList.add(command);
}
/**
* 撤销上一步命令
*/
undo() :void{
if(this.drawPathList.length > 0) {
let undo:DrawPath = this.drawPathList.get(this.drawPathList.length -1);
this.drawPathList.removeByIndex(this.drawPathList.length-1);
//撤销
undo.unDo();
this.redoList.add(undo);
}
}
//执行命令
execute(context: CanvasRenderingContext2D) {
//进行绘制
if(this.drawPathList != null) {
this.drawPathList.forEach(element => {
element.draw(context)
});
}
}
/**
* 是否可以撤销
*/
canUndo() {
return this.drawPathList.length > 0;
}
}
都是在draw文件夹下面,DrawPath.ets
import { IDraw } from './IDraw';
import Paint from './Paint';
/**
* 绘制的路径
*/
export default class DrawPath implements IDraw {
public paint: Paint = new Paint();
//绘制画笔
public path: Path2D = new Path2D();
//绘制的路径
draw(context: CanvasRenderingContext2D) {
context.lineWidth = this.paint.lineWidth;
console.info('DrawPath == ' + this.paint.strokeStyle)
context.strokeStyle = this.paint.strokeStyle
context.stroke(this.path)
}
unDo() {
}
}
IBrush.ets
export interface IBrush {
/**
* 触电接触时
*/
down(path:Path2D,x:number,y:number):void;
/**
* 触电移动时
*/
move(path:Path2D,x:number,y:number):void;
/**
* 触点停止时
* @param x
* @param y
*/
up(path:Path2D,x:number,y:number):void;
}
NormalBrush.ets
import { IBrush } from './IBrush';
export default class NormalBrush implements IBrush{
down(path: Path2D, x: number, y: number) {
path.moveTo(x,y);
}
move(path: Path2D, x: number, y: number) {
path.lineTo(x,y);
}
up(path: Path2D, x: number, y: number) {
}
}
Paint.ets
export default class Paint {
public lineWidth:number = 0;
public strokeStyle:number = 0;
// public textAlign:CanvasTextAlign = new CanvasTextAlign();
public font: string = ''
setStrokeWidth(strokeWidth:number) {
this.lineWidth = strokeWidth;
}
setColor(color:number) {
this.strokeStyle = color
}
}