HarmonyOS鸿蒙Next中我的功能设计是给出一些可参考的画面,用户可以选择在画布临摹,怎么实现呢

HarmonyOS鸿蒙Next中我的功能设计是给出一些可参考的画面,用户可以选择在画布临摹,怎么实现呢 【问题描述】:我的功能设计是给出一些可参考的画面,用户可以选择在画布临摹,怎么实现呢?

【问题现象】:我使用canvas画布来实现,现在我能够展示画布,但是我在模拟器里面点击没有办法绘制,请问绘制怎么实现

【版本信息】:NA

【复现代码】:

import { router } from '[@kit](/user/kit).ArkUI';

[@Entry](/user/Entry)
[@Component](/user/Component)
struct CanvasPages {
  [@State](/user/State) brushColor: string = '#FF6B6B'
  [@State](/user/State) brushSize: number = 5
  [@State](/user/State) paths: PathData[] = []
  [@State](/user/State) currentPath: Point[] = []
  private isDrawing: boolean = false

  build() {
    Column() {
      // 顶部工具栏
      this.buildTopBar()

      // 画布区域
      Canvas()
        .width('100%')
        .height('70%')
        .backgroundColor('#FFFFFF')
        .border({ width: 1, color: '#ECF0F1' })
        .onReady(() => {
          this.initCanvas()
        })
        .gesture(
          PanGesture({ distance: 1 })
            .onActionStart((event: GestureEvent) => {
              this.handleGestureStart(event)
            })
            .onActionUpdate((event: GestureEvent) => {
              this.handleGestureUpdate(event)
            })
            .onActionEnd(() => {
              this.handleGestureEnd()
            })
        )

      // 底部工具栏
      this.buildBottomToolbar()
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8F9FA')
  }

  [@Builder](/user/Builder)
  buildTopBar() {
    Row() {
      Button('< 返回')
        .fontSize(16)
        .fontColor('#2c3e50')
        .backgroundColor(Color.Transparent)
        .onClick(() => {
          router.back()
        })

      Text('自由创作')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .fontColor('#2c3e50')
        .layoutWeight(1)
        .textAlign(TextAlign.Center)

      Button('清除')
        .fontSize(14)
        .fontColor('#FF6B6B')
        .backgroundColor(Color.Transparent)
        .onClick(() => {
          this.clearCanvas()
        })
    }
    .width('100%')
    .padding({ left: 20, right: 20, top: 10, bottom: 10 })
    .backgroundColor(Color.White)
  }

  [@Builder](/user/Builder)
  buildBottomToolbar() {
    Column() {
      Row() {
        Text('画笔大小')
          .fontSize(14)
          .fontColor('#7f8c8d')
          .width(80)
        Slider({
          value: this.brushSize,
          min: 1,
          max: 20,
          step: 1
        })
          .layoutWeight(1)
          .padding({ left: 10, right: 10 })
          .onChange((value: number) => {
            this.brushSize = value
          })
        Text(`${this.brushSize}`)
          .fontSize(14)
          .fontColor('#2c3e50')
          .width(30)
      }
      .width('100%')
      .padding(15)

      Row() {
        Text('颜色')
          .fontSize(14)
          .fontColor('#7f8c8d')
          .width(60)

        Scroll() {
          Row({ space: 10 }) {
            ForEach(
              ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8', '#000000'],
              (color: string) => {
                Circle()
                  .width(35)
                  .height(35)
                  .fill(color)
                  .onClick(() => {
                    this.brushColor = color
                  })
                  .border({
                    width: this.brushColor === color ? 3 : 0,
                    color: '#2c3e50'
                  })
              }
            )
          }
          .padding(5)
        }
        .layoutWeight(1)
      }
      .width('100%')
      .padding(15)
      .backgroundColor(Color.White)
    }
    .backgroundColor(Color.White)
    .borderRadius(20)
    .margin(10)
    .shadow({
      radius: 10,
      color: '#00000010',
      offsetX: 0,
      offsetY: 2
    })
  }

  // 初始化画布
  private initCanvas(): void {
    console.log('画布初始化完成')
  }

  // 手势事件处理
  private handleGestureStart(event: GestureEvent): void {
    const x: number = event.offsetX
    const y: number = event.offsetY
    this.startDrawing(x, y)
  }

  private handleGestureUpdate(event: GestureEvent): void {
    if (this.isDrawing) {
      const x: number = event.offsetX
      const y: number = event.offsetY
      this.continueDrawing(x, y)
    }
  }

  private handleGestureEnd(): void {
    this.finishDrawing()
  }

  private startDrawing(x: number, y: number): void {
    this.isDrawing = true
    this.currentPath = [{ x: x, y: y }]
    console.log(`开始绘制: ${x}, ${y}`)
  }

  private continueDrawing(x: number, y: number): void {
    this.currentPath.push({ x: x, y: y })
    console.log(`继续绘制: ${x}, ${y}`)
  }

  private finishDrawing(): void {
    if (this.currentPath.length > 1) {
      this.paths.push({
        points: [...this.currentPath],
        color: this.brushColor,
        size: this.brushSize
      })
    }
    this.isDrawing = false
    this.currentPath = []
    console.log('结束绘制')
  }

  private clearCanvas(): void {
    this.paths = []
    this.currentPath = []
    console.log('清除画布')
  }
}

// 类型定义
interface Point {
  x: number
  y: number
}

interface PathData {
  points: Point[]
  color: string
  size: number
}

interface GestureEvent {
  offsetX: number
  offsetY: number
}

【尝试解决方案】:NA


更多关于HarmonyOS鸿蒙Next中我的功能设计是给出一些可参考的画面,用户可以选择在画布临摹,怎么实现呢的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

更多关于HarmonyOS鸿蒙Next中我的功能设计是给出一些可参考的画面,用户可以选择在画布临摹,怎么实现呢的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在鸿蒙Next中实现画布临摹功能,需要使用ArkUI的Canvas组件。通过CanvasRenderingContext2D的drawImage方法加载参考图作为背景,同时监听触摸事件获取用户绘制路径。使用Path2D记录笔触坐标,通过lineTo和stroke实现临摹绘制。可设置不同画笔属性控制线条样式,通过全局状态管理保存绘制数据。需注意参考图需转换为PixelMap格式进行渲染,并合理管理画布层级确保参考图位于绘制层下方。

在HarmonyOS Next中实现画布绘制功能,需要正确使用Canvas的绘制上下文。你的代码缺少了实际的绘制逻辑。以下是关键修改:

  1. 获取CanvasRenderingContext2D: 在onReady回调中获取绘制上下文:
private context: CanvasRenderingContext2D | null = null

private initCanvas(): void {
  const canvas = this.$refs.canvas // 需要给Canvas添加ref
  this.context = canvas.getContext('2d')
}
  1. 实现绘制方法: 在绘制过程中实时渲染:
private startDrawing(x: number, y: number): void {
  this.isDrawing = true
  this.currentPath = [{ x, y }]
  if (this.context) {
    this.context.beginPath()
    this.context.moveTo(x, y)
    this.context.strokeStyle = this.brushColor
    this.context.lineWidth = this.brushSize
    this.context.lineCap = 'round'
    this.context.lineJoin = 'round'
  }
}

private continueDrawing(x: number, y: number): void {
  if (this.isDrawing && this.context) {
    this.currentPath.push({ x, y })
    this.context.lineTo(x, y)
    this.context.stroke()
  }
}
  1. 添加Canvas引用: 在Canvas组件中添加ref:
Canvas()
  .ref('canvas')
  // ...其他属性
  1. 重绘逻辑: 需要添加重绘方法,在路径变化时重新渲染所有路径。

主要问题是缺少Canvas上下文的获取和实际的绘制API调用。使用CanvasRenderingContext2D的路径绘制方法即可实现触摸绘制功能。

回到顶部