鸿蒙Canvas自定义View之k线图绘制

本文介绍了如何在华为开发者联盟的平台上,利用CanvasAPI和声明式开发范式,在UI开发中创建自定义K线图。通过KLineBean数据结构和示例代码,展示了如何生成并绘制实时变化的K线图,包括高低线和开盘收盘矩形的绘制过程。
摘要由CSDN通过智能技术生成

API级别:9

参考官网文档:

使用画布绘制自定义图形(Canvas)-显示图形-基于ArkTS的声明式开发范式-UI开发-开发 | 华为开发者联盟 (huawei.com)

代码:

K线绘制代码


import { KLineBean } from '../bean/KLineBean'

@Component
export struct KLineView{

  // 开启抗锯齿
  private settings : RenderingContextSettings = new RenderingContextSettings(true)
  private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  kLineList: KLineBean[] = new Array()

  @State totalWidth:number = 300.0
  @State totalHeight:number = 100.0
  kLineNum = 30
  linePadding = 0.2
  lineWidth = 0.2

  uH = 0.0
  uW = 0.0

  aboutToAppear(){

    // 初始化数据
    for(let i = 0; i < this.kLineNum; i++){
      let kLineBean = new KLineBean()
      kLineBean.low = Math.floor(Math.random() * 100)
      kLineBean.high = kLineBean.low + 30
      kLineBean.open = kLineBean.low + Math.floor(Math.random() * 30)
      kLineBean.close = kLineBean.low + Math.floor(Math.random() * 30)

      this.kLineList.push(kLineBean)
    }

    this.uH = this.calculatorUnitH(this.kLineList)
    this.uW = (this.totalWidth - 20) / this.kLineNum - this.linePadding * 2
  }

  calculatorUnitH(kLineList: KLineBean[]): number{
    let result = 0.0
    let lowNum = Number.MAX_VALUE
    let highNum = 0.0

    for(let i =0; i <kLineList.length; i++){
      let bean = kLineList[i]
      if(lowNum > bean.low){
        lowNum = bean.low
      }

      if(highNum < bean.high){
        highNum = bean.high
      }
    }
    result =  (this.totalHeight)/(highNum - lowNum)

    return result
  }


  /**
   * 1.设置控件宽高
   * 2.根据控件高度的最大和最小值之差,得到绘图的单位长度 unitH = 差/ (高度 - padding)
   * 3.根据k线数据数量,得到单位K线的宽度 unitW = w/number
   * 4.绘制每根K线的高低线和开盘收盘矩形,并根据开盘收盘价来设置绘制颜色
   */
  build(){
    Flex(){
      Canvas(this.canvasContext).width("100%").height("100%").backgroundColor('#ffffff').onReady(()=>{
        this.canvasContext.strokeStyle = '#EDEEEF'
        this.canvasContext.strokeRect(0, 0, this.totalWidth, this.totalWidth)



        for(let i = 0; i < this.kLineList.length; i++){

          let bean = this.kLineList[i]

          console.log(" testTag  low:" + bean.low + "  high:" + bean.high + "  open:" + bean.open + "  close:" + bean.close)
          /// 画线 1.定位线的起点和终点 起点纵轴为 控件高度 - (uH * high), 终点为 控件高度 - (uH * low)
          ///       起点横轴为 i * uW  + uW/2 + linePadding

          // 设置直线的颜色
          if(bean.close > bean.open){
            this.canvasContext.strokeStyle = '#ff0000'
          }else{
            this.canvasContext.strokeStyle = '#00ff00'
          }

          this.canvasContext.lineWidth = this.lineWidth
          this.canvasContext.beginPath()
          this.canvasContext.moveTo( i * this.uW + this.uW / 2 + (2 * i + 1) * this.linePadding ,this.totalHeight - (this.uH * bean.high))
          this.canvasContext.lineTo( i * this.uW + this.uW / 2 + (2 * i + 1) * this.linePadding ,this.totalHeight - (this.uH * bean.low))
          this.canvasContext.stroke()

          /// 画矩形: 纵轴为 控件高度 - (uH * Math.max(open, close)) 横轴为 i * (uW + linePadding * 2)
          ///      宽为 uW,高为 (uH * Math.abs(open - close)
          if(bean.close > bean.open){
            this.canvasContext.fillStyle = '#ff0000'
          }else{
            this.canvasContext.fillStyle = '#00ff00'
          }
          let y = this.totalHeight - (this.uH * Math.max(bean.open, bean.close))
          let x = i * (this.uW + this.linePadding * 2) + this.linePadding
          let w = this.uW
          let h = this.uH * Math.abs(bean.close - bean.open)
          if(h == 0){
            h = 1;
          }
          this.canvasContext.fillRect(x,y, w,h)

        }

      })
    }.width('100%').height('100%').padding({left:20})

  }

  positionXStart(index: number): number{
    return index * (this.uW + this.linePadding * 2)
  }

  positionXCenter(index: number):number{
    return  index * this.uW + this.uW / 2 + (2 * index + 1) * this.linePadding
  }

}

数据结构代码:


export class KLineBean{
  low: number
  high: number
  open: number
  close: number
  date : string
}

应用效果:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值