鸿蒙开发:简单自定义一个绘制画板

简介: 画板,最重要的就是绘制,保证线条绘制的连续性,这一点很重要,还有就是beginPath方法一定要调用,否则更改颜色以及绘制就会出现不连续以及颜色设置错误问题。

前言


本篇文章,主要是使用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方法一定要调用,否则更改颜色以及绘制就会出现不连续以及颜色设置错误问题。

相关文章
|
7月前
|
XML 搜索推荐 Java
Android App开发之自定义图形中位图与图形互转、剪裁图形内部区域、给图形添加部件的讲解及实战(附源码 简单易懂)
Android App开发之自定义图形中位图与图形互转、剪裁图形内部区域、给图形添加部件的讲解及实战(附源码 简单易懂)
75 0
|
7月前
|
XML 前端开发 Java
Android Studio App自定义控件中自定义视图的绘制讲解及实战(附源码 包括自定义绘制各种图形)
Android Studio App自定义控件中自定义视图的绘制讲解及实战(附源码 包括自定义绘制各种图形)
110 1
|
4天前
【HarmonyOS Next开发】实现矩形上下拖动、动态拖拽修改高度
实现一个矩形块上下拖动,并且可以拖动边缘定位点改变矩形块高度。
20 6
|
1月前
|
UED 开发者
鸿蒙next版开发:ArkTS组件通用属性(图片边框设置)
在HarmonyOS 5.0中,ArkTS提供了灵活的图片边框设置属性,使开发者可以为应用中的图片组件添加各种边框效果,提升视觉效果和用户体验。本文详细解读了ArkTS中图片边框设置的通用属性,并提供了示例代码。通过设置`borderImage`属性,可以控制边框的图源、切割宽度、边框宽度、延伸距离、平铺模式和是否填充。示例代码展示了如何使用这些属性来创建具有不同边框效果的图片组件。图片边框设置在美化界面、区分内容和增强交互方面有重要作用。
81 5
|
1月前
|
API 开发者 UED
鸿蒙next版开发:ArkTS组件通用属性(形状裁剪)
在HarmonyOS 5.0中,ArkTS引入了形状裁剪的通用属性,支持矩形、圆形、椭圆及自定义路径等多种形状的裁剪和遮罩处理。本文详细解读了clip、clipShape、mask和maskShape属性,并提供了示例代码,帮助开发者实现多样化的界面设计和动画效果。
130 1
|
1月前
|
前端开发 开发者
深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画
本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。
84 1
|
4月前
|
前端开发
Flutter快速实现自定义折线图,支持数据改变过渡动画
Flutter快速实现自定义折线图,支持数据改变过渡动画
113 4
|
编解码 Android开发
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(一)
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(一)
538 0
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(一)
|
Android开发
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(二)
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(二)
433 0
【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )(二)
|
Android开发 容器
【鸿蒙 HarmonyOS】Ability 中使用纯代码绘制布局及 UI 组件
【鸿蒙 HarmonyOS】Ability 中使用纯代码绘制布局及 UI 组件
315 0
【鸿蒙 HarmonyOS】Ability 中使用纯代码绘制布局及 UI 组件