前言
本篇文章,主要是使用Canvas绘制一个简单的画板,可以更改颜色,画笔粗细以及删除操作,主要运用到了CanvasRenderingContext2D中的绘制路径功能,我们可以看下基本实现的效果。
若在一个画板上进行随意的绘制,少不了画布的存在,鸿蒙当中为我们提供了Canvas组件,使用它,我们可以在上面进行绘制各种想要的图形,共有两个构造参数,可以只接收一个context参数,主要用于设置绘制的能力,除了context参数,也可以接收一个ImageAIOptions参数,主要用于需要AI分析选项的时候,一般传递一个参数就可以。
(context?: CanvasRenderingContext2D | DrawingRenderingContext): CanvasAttribute
CanvasRenderingContext2D比DrawingRenderingContext功能设置更加丰富,而且兼容其自身所带的功能,所以,在绘制元素上,还是建议使用CanvasRenderingContext2D。
设置画布
Canvas是一个组件,我们之间可以像其他组件一样进行使用。
Canvas(this.context) .width('100%') .height('100%')
传递的是一个CanvasRenderingContext2D对象。
private settings: RenderingContextSettings = new RenderingContextSettings(true) private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
RenderingContextSettings是用来配置CanvasRenderingContext2D对象的参数,可以设置是否开启抗锯齿。
路径绘制
路径绘制,包括了手指按下的开始路径,移动路径到指定点,以及手指移动时的点到指定点的路径连接,还有最后的路径结束,这样的流程,才能让线条绘制的更加丝滑,更加符合正常的使用。
.onTouch((event: TouchEvent) => { switch (event.type) { case TouchType.Down:// let downTouch = event.touches[0] this.context.beginPath() this.context.moveTo(downTouch.x, downTouch.y) break case TouchType.Move: let touch = event.touches[0] this.context.lineTo(touch.x, touch.y) this.context.stroke() break case TouchType.Up: this.context.closePath() break } })
设置抗锯齿
通过设置抗锯齿,可以去掉线条的毛边,让线条变得丝滑顺畅。
Canvas(this.context) .width('100%') .height('100%') .onReady(() => { this.settings.antialias = true//打开抗锯齿 this.context.lineCap = "round"//设置指定线端点的样式,圆形 })
清除操作
this.context.clearRect(0, 0, this.context.width, this.context.height)
完整代码
@Entry @Component struct Index { private settings: RenderingContextSettings = new RenderingContextSettings(true) private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) private mColors: string[] = ["#000000", "#ffffff", "#FF050C", "#FF7F1D", "#FFE613", "#B2FF29", "#31FFCA", "#2253FF", "#DA25FF", "#FFA687", "#ACFFD3", "#98C8FF", "#B8ACFF", "#FFCFC5", "#FFDF91"] @State showListColor: boolean = true @State sliderProgress: string = "" build() { Column() { Canvas(this.context) .width('100%') .height('100%') .onReady(() => { this.settings.antialias = true this.context.lineCap = "round" }) .onTouch((event: TouchEvent) => { switch (event.type) { case TouchType.Down: let downTouch = event.touches[0] this.context.beginPath() this.context.moveTo(downTouch.x, downTouch.y) break case TouchType.Move: let touch = event.touches[0] this.context.lineTo(touch.x, touch.y) this.context.stroke() break case TouchType.Up: this.context.closePath() break } }) .layoutWeight(1) //颜色 List({ space: 10 }) { ForEach(this.mColors, (item: string, _: number) => { ListItem() { Text() .width(20) .height(20) .backgroundColor(item) .borderRadius(20) .border({ width: 1, color: "#e8e8e8" }) .onClick(() => { this.context.strokeStyle = item }) } }) } .width("100%") .height(40) .listDirection(Axis.Horizontal) .scrollBar(BarState.Off) .alignListItem(ListItemAlign.Center) .border({ width: { top: 1 }, color: "#e8e8e8" }) .visibility(this.showListColor ? Visibility.Visible : Visibility.Hidden) Slider({ value: 0, min: 0, max: 50, style: SliderStyle.OutSet }) .showTips(true, this.sliderProgress) .trackThickness(5) .onChange((value: number, _: SliderChangeMode) => { this.sliderProgress = value.toString() this.context.lineWidth = value }) Row() { Image($r("app.media.canvas_del")) .width(30) .height(30) .borderRadius(30) .border({ width: 1, color: "#e8e8e8" }) .padding(5) .onClick(() => { //橡皮擦 this.context.strokeStyle = "#ffffff" }) Image($r("app.media.canvas_clear")) .width(30) .height(30) .borderRadius(30) .border({ width: 1, color: "#e8e8e8" }) .margin({ left: 20 }) .padding(5) .onClick(() => { //清空 this.context.clearRect(0, 0, this.context.width, this.context.height) }) }.width("100%") .height(50) .border({ width: { top: 1 }, color: "#e8e8e8" }) .justifyContent(FlexAlign.Center) } } }
相关总结
画板,最重要的就是绘制,保证线条绘制的连续性,这一点很重要,还有就是beginPath方法一定要调用,否则更改颜色以及绘制就会出现不连续以及颜色设置错误问题。