HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)

系列文章目录

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
HarmonyOS Next 系列之可移动悬浮按钮实现(六)
HarmonyOS Next 系列之沉浸式状态实现的多种方式(七)
HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)
HarmonyOS Next系列之地图组件(Map Kit)使用(九)
HarmonyOS Next系列之半圆环进度条实现(十)
HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)
HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图(十二)
HarmonyOS Next系列之水波纹动画特效实现(十三)
HarmonyOS Next系列之华为账号一键登录功能实现(十四)


系列文章目录2

【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(上)
【鸿蒙】HarmonyOS NEXT开发快速入门教程之ArkTS语法装饰器(下)
【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇(上)
【鸿蒙】HarmonyOS NEXT应用开发快速入门教程之布局篇(下)
【鸿蒙】HarmonyOS Next 组件或页面之间的所有通信(传参)方法总结



前言

HarmonyOS Next(基于API11)实现Echarts图表组件(折线图、柱状图、饼图等)。

Echarts作为web端最流行开源的图表库,有着
多种图表类型,丰富的配置、强大的交互功能、可扩展性强等优点,如果能在鸿蒙上使用对于熟悉web开发同学将无缝衔接,大大减少开发和学习成本。

在这里插入图片描述
在这里插入图片描述


一、实现原理分析

echarts作为JavaScript实现的开源可视化库只能通过网页形式渲染,所以可以 通过web组件内嵌本地网页形式混合开发。web和应用交互则通过WebviewController.runJavaScript(code)形式往网页注入执行代码。

二、代码实现

1.项目内新建本地html文件引入echarts.min.js

resources/rawfile目录下新建echarts.html和添加echarts.min.js

在这里插入图片描述
echarts.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport"/>
    <script src="./echarts.min.js"></script>
    <style>
        *{
     padding:0;
     margin:0
    }
    body,html{
       height:100%;
       width:100%
    }
    #container{
       height:100%;
       width:100%
    }
    </style>
</head>
<body>
<div id="container"></div>
</body>
<script>
    const container = document.getElementById('container')
    let myChart = echarts.init(container);

    function setOption(option){
         myChart?.clear();
         myChart?.setOption(option)
    }

</script>
</html>

echarts.min.js

可以从官网在线定制下载echart.js定制

说明:此步骤新建了一个html文件引入了echarts.min.js并初始化echarts,定义了一个
setOption方法,后续通过调用该方法传入配置就能渲染出图表

2.Echart.ets组件封装

在这里插入图片描述

封装一个全局通用的echart组件,目录结构如上图所示,其中Echarts.ets为组件文件,ViewModel.ets为图表相关配置数据类型定义

Echarts.ets

import webview from '@ohos.web.webview'

@Component
export default struct Echarts {
  //控制器
  controller: webview.WebviewController = new webview.WebviewController();
  //组件宽
  @Prop eWidth: string | number = '100%'
  //组件高,单位vp
  @Prop eHeight: string | number = 300
  //渲染完成回调
  renderCallBack: (e: Echarts) => void = () => {
  }

  //更新或渲染组件
  render(option: Record<string, ESObject> | string) {
    this.controller.runJavaScript(`setOption(${typeof option === 'string' ? option : JSON.stringify(option)})`)
  }

  build() {
    Column() {
      Web({ src: $rawfile('echarts.html'), controller: this.controller })
        .width('100%')
        .height('100%')
        .onPageEnd(e => {
          this.renderCallBack && this.renderCallBack(this)
        })

    }
    .width(this.eWidth)
    .height(this.eHeight)
  }
}

说明:

组件定义了长宽属性,默认宽度100%,高度300vp,
renderCallBack回调函数作用把整个echarts组件实例暴露给引用页面。
render方法重新加载渲染组件,入参为图表配置,入参既可以是对象也可以是字符串,无论何种类型最终都将转换为字符串注入web执行。

在引用页面通过renderCallBack暴露出去的实例调用render方法即可自由刷新图表数据

ViewModel.ets:

/**
 * echart配置数据类型定义
 */
export interface EChartsOption {
  grid?: EchartGrid,
  title?: EChartsTitle;
  tooltip?: EChartsTooltip;
  legend?: EChartsLegend;
  xAxis: EChartsXAxis;
  yAxis: EChartsYAxis;
  series: EChartsSeries[];
}

export  interface EchartGrid {
  top?: number|string
  bottom?: number|string
  left?: number|string
  right?: number|string
}

export interface EChartsTitle {
  text?: string;
}

export interface EChartsTooltip {}

export interface EChartsLegend {
  show?:boolean
  data?: string[];
}


export interface EChartsXAxis {
  type?: string;
  data: string[];
  axisLine?: XAxisAxisLine;
  axisTick?: XAxisAxisTick
  boundaryGap?: boolean | Array<string>
  axisLabel?: AxisLabel

}

export interface XAxisAxisLine {
  show?: boolean
}

export interface XAxisAxisTick {
  show?: boolean
}


export interface EChartsYAxis {
  type?: string
  splitLine?: YAxisSplitLine
  splitNumber?: number
  min?: number
  max?: number
  scale?: boolean
  interval?: number

}

export interface AxisLabel {
  show?: boolean
  formatter?: string | ((value: number | string, index: number) => string)
}

export interface YAxisSplitLine {
  lineStyle?: AxisSplitLineLineStyle
}

export interface AxisSplitLineLineStyle {
  type?: string
}

export interface EChartsSeries {
  name?: string;
  type?: string;
  data: number[];

}

ViewModel.ets里面定义了一些常见的图表配置数据结构(类型),方便在引入页中引入使用,可以按需继添加扩展

3.页面使用

Index.ets

import Echarts from '../components/Echarts/Echarts'
import { EChartsOption } from '../components/Echarts/ViewModel'

@Entry
@Component
struct Index {
  //图表实例
  myEchart: Echarts | null = null
  /*
   * 图表配置
   */
  option: EChartsOption = {
  //标题
    title: {
      text: '基础柱状图'
    },
    //图例
    legend: {
      data: ['访问量']
    },
    //x轴配置
    xAxis: {
      type: 'category',
      data: []
    },
    //y轴配置
    yAxis: {
      type: 'value'
    },
    //数据配置
    series: [
      {
        data: [],
        type: 'bar',//柱状图
        name: '访问量'
      }
    ]
  };

  aboutToAppear(): void {
    this.getData()
  }

  //接口请求获取数据
  getData() {
    //模拟接口请求
    setTimeout(() => {
      //设置x轴数据
      this.option.xAxis.data = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
      //设置y轴数据
      this.option.series[0].data = [120, 200, 150, 80, 70, 110, 130]
      //调用render重新渲染
      this.myEchart?.render(this.option)
    }, 2000)
  }

  // 组件实例
  chart?: Echarts;

  build() {
    Column() {
      Echarts({
        eHeight: 300,
        //回调
        renderCallBack: (e: Echarts) => {
          this.myEchart = e
          //初次渲染组件,接口获取数据是异步此时this.option可能还没有新数据
          this.myEchart.render(this.option)
        }
      })
    }
    .width('100%')
    .height('100%')
  }
}

运行效果:

在这里插入图片描述


三、配置项含函数需特殊处理

对于配置项包含函数的情况,例如坐标轴标签设置AxisLabel.formatter字段可以是个函数类型,此时就需要特殊处理。这是因为当我们传递option为对象给render函数时候

this.controller.runJavaScript(`setOption(${typeof option === 'string' ? option : JSON.stringify(option)})`)

此时调用JSON.stringify把对象转换为字符串,而JSON.stringify入参内函数会直接被去掉。
因此我们需要自己把option处理成字符串传入即可

代码示例:

给折线图y轴刻度值加个万字

Index.ets

import Echarts from '../components/Echarts/Echarts'

@Entry
@Component
struct Index {
  //图表配置
  @State option: string = ``
  //x轴数据
  @State xAxisData: string[] = [];
  //y轴数据
  @State seriesData: number[] = [];
  myEchart: Echarts | null = null;

  aboutToAppear(): void {
    this.getData()
  }

  /*
   * 设置配置并重新渲染
   */
  setOption() {
    this.option = `{
    title: {
      text: '基础柱折线图'
    },
    grid:{
      left:"15%"
    },
    legend:{
      data: ['访问量']
    },
    xAxis: {
      type: 'category',
      data: ${JSON.stringify(this.xAxisData)}
    },
    yAxis: {
      axisLabel: {
        show: true,
        formatter:(value, index)=> {
            return value + '万';
        }
      }
    },
    series: [
      {
        data: ${JSON.stringify(this.seriesData)},
        type: 'line',
        name:'访问量'
      }
    ]
  }`
    this.myEchart?.render(this.option)
  }

  //接口请求获取数据
  getData() {
    //模拟接口请求
    setTimeout(() => {
      this.xAxisData = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
      this.seriesData = [120, 200, 150, 80, 70, 110, 130]
      this.setOption()
    }, 2000)
  }

  // 组件实例
  chart?: Echarts;

  build() {
    Column() {
        Echarts({
          eHeight: 300,
          renderCallBack: (e: Echarts) => {
            this.myEchart = e
            this.setOption()
          }
        })

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

运行效果:
在这里插入图片描述


总结

当然作为混合开发产物性能自然比上不上原生,但是echarts有着跨平台兼容性好等优点,对付数据量不大、交互要求不高的场景绰绰有余。目前处于起步发展阶段的鸿蒙来说还没有一款稳定成熟、配置丰富能满足各种ui设计要求的官方或三方组件库。所以只要你的开发场景对性能要求不高,web形式的echart也是个不错的选择,尤其能实现各种定制化ui。

### 使用鸿蒙ArkTS实现数据可视化鸿蒙操作系统中,通过ArkTS可以利用`Echarts`来创建丰富的图表组件。对于而言,在HarmonyOS Next(基于API11)环境中可以通过集成第三方库或使用内置支持的数据可视化工具完成。 #### 创建项目并引入依赖项 为了能够在应用程序内显示,首先需要确保项目的构建配置文件已经包含了必要的依赖声明。如果采用的是类似于ECharts这样的解决方案,则需按照官方指南添加相应的模块引用[^1]。 ```json { "dependencies": { "@ohos/echarts": "^latest" } } ``` #### 初始化视容器 接着,在页面布局XML文件里定义一个用于容纳图表的区域: ```xml <!-- layout/index.hml --> <div class="chart-container"> <!-- 这里放置图表 --> </div> ``` 同时设置样式以适应不同尺寸屏幕上的展示效果: ```css /* style/index.css */ .chart-container { width: 100%; height: 400px; } ``` #### 编写逻辑代码绘制 最后一步是在TypeScript文件中编写具体的绘逻辑。这里给出一段简单的例子说明如何初始化以及渲染一张基本的: ```typescript // entry/src/main/js/default/index.ts import { createApp } from '@ohos/arkui'; import * as echarts from '@ohos/echarts'; createApp({ onInit() { const chartContainer = document.querySelector('.chart-container'); let myChart = echarts.init(chartContainer); let option = { title : { text: '某站点用户访问来源', subtext: '纯属虚构', left: 'center' }, tooltip : { trigger: 'item' }, legend: { orient: 'vertical', left: 'left' }, series : [ { name: '访问来源', type: 'pie', radius : '55%', center: ['50%', '60%'], data:[ {value:335, name:'直接访问'}, {value:310, name:'邮件营销'}, {value:234, name:'联盟广告'}, {value:135, name:'视频广告'}, {value:1548, name:'搜索引擎'} ], emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] }; myChart.setOption(option); } }); ``` 上述代码片段展示了如何在一个新的鸿蒙应用工程下快速搭建起能够呈现简单状统计形的功能模块。需要注意的是实际开发过程中可能还需要处理更多细节问题比如响应式设计、交互事件绑定等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pixle0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值