HarmonyOS-Canvas画布组件

声明

本文依赖文章canvas详细入门教程(1W字 吐血分享),讲解了harmonyOS的Canvas的使用,在内容上做了一定的精简,完整学习Canvas建议点击链接

构造canvas对象

这是官网的案例

使用CanvasRenderingContext2D对象在Canvas画布上绘制。

@Entry
@Component
struct CanvasExample1 {
  //用来配置CanvasRenderingContext2D对象的参数,包括是否开启抗锯齿,true表明开启抗锯齿。
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //用来创建CanvasRenderingContext2D对象,通过在canvas中调用CanvasRenderingContext2D对象来绘制。
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      //在canvas中调用CanvasRenderingContext2D对象。
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() => {
          //可以在这里绘制内容。
          this.context.strokeRect(50, 50, 200, 150);
        })

    }
    .width('100%')
    .height('100%')
  }
}

重点---在Canvas里绘制

Canvas的绘制主要在onReady()事件回调里

坐标系:以左上角为起点

一、绘制基础图形

画线之前你需要知道canvas上下文的以下几个api:

moveTo(x,y):定义画线的起始点;

lineTo(x,y):定义画线的折点;

stroke():通过线条来绘制图形轮廓

beginPath():开启一条新的路径
closePath();关闭路径

1.画线段

@Entry
@Component
struct CanvasExample2 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
      .height('100%')
      .backgroundColor('#ffffffff')
      .onReady(() =>{

        // 画线段
        this.context.beginPath()
        this.context.moveTo(150,150)
        this.context.lineTo(300,150)
        this.context.stroke()

        this.context.beginPath()
        this.context.moveTo(150,450)
        this.context.lineTo(300,450)


      })
    }
    .width('100%')
    .height('100%')
  }
}

如果没有调用 this.context.stroke()第二条线实际上并不会在画布上显示出来,因为
this.context.moveTo(150,450)
this.context.lineTo(300,450)
这些方法只是定义了路径,并没有绘制它。

2. 画三角形

@Entry
@Component
struct CanvasExample2 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
      .height('100%')
      .backgroundColor('#ffffffff')
      .onReady(() =>{

        // 画三角形
        this.context.beginPath()
        this.context.moveTo(150,150)  // 起点坐标
        this.context.lineTo(300,150)  
        this.context.lineTo(300,300)
        this.context.lineTo(150,150)
        this.context.closePath()    
        this.context.lineWidth=20   //设置线段宽度
        this.context.strokeStyle='blue'  //设置线段颜色
        
        // 注意,要在stroke() 前设置样式,否者会显示不出来
        
        this.context.stroke()


      })
    }
    .width('100%')
    .height('100%')
  }
}

3.画矩形 

@Entry
@Component
struct CanvasExample3 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffffff')
        .onReady(() =>{
          this.context.beginPath()
        this.context.rect(40,40,160,90)
          this.context.closePath()
          this.context.lineWidth=20   //设置线段宽度
          this.context.strokeStyle='blue'  //设置线段颜色

          // 注意,要在stroke() 前设置样式,否者会显示不出来

          this.context.stroke()
        })
    }
    .width('100%')
    .height('100%')
  }
}

 4.画圆形

@Entry
@Component
struct CanvasExample4 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffffff')
        .onReady(() =>{
          //绘制圆形
          this.context.beginPath();
          this.context.arc(150, 250, 50, 0, 6.28);
          this.context.stroke();

          //绘制半圆形
          this.context.beginPath();
          this.context.arc(150, 350, 50, 0, 3.14);
          this.context.stroke();
        })
    }
    .width('100%')
    .height('100%')
  }
}

 5.画椭圆

@Entry
@Component
struct CanvasExample5 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffffff')
        .onReady(() =>{
          //绘制椭圆
          this.context.beginPath();
          this.context.ellipse(150, 350, 50, 100, Math.PI * 0.25, Math.PI * 0, Math.PI * 2);
          this.context.stroke();
        })
    }
    .width('100%')
    .height('100%')
  }
}

 二.设置文本

可以通过fillText(绘制填充类文本)、strokeText(绘制描边类文本)等接口进行文本绘制。



@Entry
@Component
struct Canvas_demo_04 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffffff')
        .onReady(() =>{
          this.context.font ='20vp' //.font方法可以设置文本大小和字体;
          this.context.beginPath()
          this.context.strokeText('hello world',100,100,200)
          this.context.closePath()

          this.context.beginPath()
          this.context.font ='100vp'
          this.context.strokeText('hello world',100,300,200)
          this.context.closePath()


          this.context.beginPath()
          this.context.fillText('这是文本',100,600,100)



        })
    }
    .width('100%')
    .height('100%')
  }
}

三.样式补充

渐变色


//渐变色
@Entry
@Component
struct CanvasDemo_05 {
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffffffff')
        .onReady(() => {
          // 创建渐变
          let gradient = this.context.createLinearGradient(0, 0, 700, 0);
          gradient.addColorStop(0, Color.Green.toString());
          gradient.addColorStop(1, Color.Red.toString());

          // 填充渐变背景
          this.context.beginPath();
          this.context.fillStyle = gradient;
          this.context.fillRect(0, 0, 700, 600);
          this.context.fill();


        });
    }
    .width('100%')
    .height('100%')
  }
}

 四.使用案例

使用Canvas绘制气温变化图

@Entry
@Component
struct TempLineChart {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  // 定义气温和小时数组
  private Temp: number[] = [18, 20, 21, 21, 22, 23, 25, 27, 29, 30, 32, 34, 36, 35, 32, 30, 27, 26, 24, 22, 21, 20, 20, 19]
  private Hour: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
  build() {
    Scroll(){
      Canvas(this.context)
        .width(680)
        .height(300)
        .backgroundColor('#ffffffff')
        .onReady(() => {
          this.drawChart()
        })
    }
    .scrollable(ScrollDirection.Horizontal)
  }
  // 绘制折线图函数
  drawChart() {
    const width: number = 680
    const height: number = 300

    // 定义绘图区域的边距
    const padding: number = 40
    const graphWidth: number = width - 2 * padding
    const graphHeight: number = height - 2 * padding

    // 绘制坐标轴
    this.drawAxes(padding, graphWidth, graphHeight)

    // 绘制折线
    this.drawLine(padding, graphWidth, graphHeight)

    // 绘制X轴小时数
    this.drawXAxisLabels(padding, graphWidth, graphHeight)
  }

  // 绘制坐标轴函数
  drawAxes(padding: number, graphWidth: number, graphHeight: number) {
    this.context.strokeStyle = '#000000'
    this.context.lineWidth = 2

    // 绘制X轴
    this.context.beginPath()
    this.context.moveTo(padding, padding + graphHeight)
    this.context.lineTo(padding + graphWidth, padding + graphHeight)
    this.context.stroke()

    // 绘制Y轴
    this.context.beginPath()
    this.context.moveTo(padding, padding)
    this.context.lineTo(padding, padding + graphHeight)
    this.context.stroke()
  }

  // 绘制折线函数
  drawLine(padding: number, graphWidth: number, graphHeight: number) {
    this.context.strokeStyle = '#ff0000'
    this.context.lineWidth = 2

    // 根据气温和小时数据计算折线图的点
    this.context.beginPath()
    for (let i = 0; i < this.Hour.length; i++) {
      const x = padding + (graphWidth / (this.Hour.length - 1)) * i
      const y = padding + graphHeight - 30-(graphHeight / 20) * (this.Temp[i] - 18)
      if (i === 0) {
        this.context.moveTo(x, y)
      } else {
        this.context.lineTo(x, y)
      }

      this.context.fillText(this.Temp[i].toString()+'°', x, y-20)
    }

    this.context.stroke()
  }

  // 绘制X轴小时数函数
  drawXAxisLabels(padding: number, graphWidth: number, graphHeight: number) {
    this.context.fillStyle = '#000000'
    this.context.font = '30px Arial'
    this.context.textAlign = 'center'

    for (let i = 0; i < this.Hour.length; i++) {
      const x = padding + (graphWidth / (this.Hour.length - 1)) * i
      const y = padding + graphHeight + 20 // 调整标签的位置
      this.context.fillText(this.Hour[i].toString(), x, y)
    }
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值