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

打印 上一主题 下一主题

主题 1003|帖子 1003|积分 3011

系列文章目次

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP哀求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
HarmonyOS Next 系列之可移动悬浮按钮实现(六)
HarmonyOS Next 系列之沉醉式状态实现的多种方式(七)
HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)


  

前言

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:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <meta charset="utf-8">
  5.     <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport"/>
  6.     <script src="./echarts.min.js"></script>
  7.     <style>
  8.         *{
  9.      padding:0;
  10.      margin:0
  11.     }
  12.     body,html{
  13.        height:100%;
  14.        width:100%
  15.     }
  16.     #container{
  17.        height:100%;
  18.        width:100%
  19.     }
  20.     </style>
  21. </head>
  22. <body>
  23. <div id="container"></div>
  24. </body>
  25. <script>
  26.     const container = document.getElementById('container')
  27.     let myChart = echarts.init(container);
  28.     function setOption(option){
  29.          myChart?.clear();
  30.          myChart?.setOption(option)
  31.     }
  32. </script>
  33. </html>
复制代码
echarts.min.js
   可以从官网在线定制下载echart.js定制
  说明:此步骤新建了一个html文件引入了echarts.min.js并初始化echarts,界说了一个
setOption方法,后续通过调用该方法传入配置就能渲染出图表
2.Echart.ets组件封装


   封装一个全局通用的echart组件,目次结构如上图所示,此中Echarts.ets为组件文件,ViewModel.ets为图表相干配置数据类型界说
  Echarts.ets
  1. import webview from '@ohos.web.webview'
  2. @Component
  3. export default struct Echarts {
  4.   //控制器
  5.   controller: webview.WebviewController = new webview.WebviewController();
  6.   //组件宽
  7.   @Prop eWidth: string | number = '100%'
  8.   //组件高,单位vp
  9.   @Prop eHeight: string | number = 300
  10.   //渲染完成回调
  11.   renderCallBack: (e: Echarts) => void = () => {
  12.   }
  13.   //更新或渲染组件
  14.   render(option: Record<string, ESObject> | string) {
  15.     this.controller.runJavaScript(`setOption(${typeof option === 'string' ? option : JSON.stringify(option)})`)
  16.   }
  17.   build() {
  18.     Column() {
  19.       Web({ src: $rawfile('echarts.html'), controller: this.controller })
  20.         .width('100%')
  21.         .height('100%')
  22.         .onPageEnd(e => {
  23.           this.renderCallBack && this.renderCallBack(this)
  24.         })
  25.     }
  26.     .width(this.eWidth)
  27.     .height(this.eHeight)
  28.   }
  29. }
复制代码
说明:
组件界说了长宽属性,默认宽度100%,高度300vp,
renderCallBack回调函数作用把整个echarts组件实例暴露给引用页面。
render方法重新加载渲染组件,入参为图表配置,入参既可以是对象也可以是字符串,无论何种类型最终都将转换为字符串注入web执行。
在引用页面通过renderCallBack暴露出去的实例调用render方法即可自由刷新图表数据
ViewModel.ets:
  1. /**
  2. * echart配置数据类型定义
  3. */
  4. export interface EChartsOption {
  5.   grid?: EchartGrid,
  6.   title?: EChartsTitle;
  7.   tooltip?: EChartsTooltip;
  8.   legend?: EChartsLegend;
  9.   xAxis: EChartsXAxis;
  10.   yAxis: EChartsYAxis;
  11.   series: EChartsSeries[];
  12. }
  13. export  interface EchartGrid {
  14.   top?: number|string
  15.   bottom?: number|string
  16.   left?: number|string
  17.   right?: number|string
  18. }
  19. export interface EChartsTitle {
  20.   text?: string;
  21. }
  22. export interface EChartsTooltip {}
  23. export interface EChartsLegend {
  24.   show?:boolean
  25.   data?: string[];
  26. }
  27. export interface EChartsXAxis {
  28.   type?: string;
  29.   data: string[];
  30.   axisLine?: XAxisAxisLine;
  31.   axisTick?: XAxisAxisTick
  32.   boundaryGap?: boolean | Array<string>
  33.   axisLabel?: AxisLabel
  34. }
  35. export interface XAxisAxisLine {
  36.   show?: boolean
  37. }
  38. export interface XAxisAxisTick {
  39.   show?: boolean
  40. }
  41. export interface EChartsYAxis {
  42.   type?: string
  43.   splitLine?: YAxisSplitLine
  44.   splitNumber?: number
  45.   min?: number
  46.   max?: number
  47.   scale?: boolean
  48.   interval?: number
  49. }
  50. export interface AxisLabel {
  51.   show?: boolean
  52.   formatter?: string | ((value: number | string, index: number) => string)
  53. }
  54. export interface YAxisSplitLine {
  55.   lineStyle?: AxisSplitLineLineStyle
  56. }
  57. export interface AxisSplitLineLineStyle {
  58.   type?: string
  59. }
  60. export interface EChartsSeries {
  61.   name?: string;
  62.   type?: string;
  63.   data: number[];
  64. }
复制代码
ViewModel.ets内里界说了一些常见的图表配置数据结构(类型),方便在引入页中引入使用,可以按需继添加扩展
3.页面使用

Index.ets
  1. import Echarts from '../components/Echarts/Echarts'
  2. import { EChartsOption } from '../components/Echarts/ViewModel'
  3. @Entry
  4. @Component
  5. struct Index {
  6.   //图表实例
  7.   myEchart: Echarts | null = null
  8.   /*
  9.    * 图表配置
  10.    */
  11.   option: EChartsOption = {
  12.   //标题
  13.     title: {
  14.       text: '基础柱状图'
  15.     },
  16.     //图例
  17.     legend: {
  18.       data: ['访问量']
  19.     },
  20.     //x轴配置
  21.     xAxis: {
  22.       type: 'category',
  23.       data: []
  24.     },
  25.     //y轴配置
  26.     yAxis: {
  27.       type: 'value'
  28.     },
  29.     //数据配置
  30.     series: [
  31.       {
  32.         data: [],
  33.         type: 'bar',//柱状图
  34.         name: '访问量'
  35.       }
  36.     ]
  37.   };
  38.   aboutToAppear(): void {
  39.     this.getData()
  40.   }
  41.   //接口请求获取数据
  42.   getData() {
  43.     //模拟接口请求
  44.     setTimeout(() => {
  45.       //设置x轴数据
  46.       this.option.xAxis.data = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  47.       //设置y轴数据
  48.       this.option.series[0].data = [120, 200, 150, 80, 70, 110, 130]
  49.       //调用render重新渲染
  50.       this.myEchart?.render(this.option)
  51.     }, 2000)
  52.   }
  53.   // 组件实例
  54.   chart?: Echarts;
  55.   build() {
  56.     Column() {
  57.       Echarts({
  58.         eHeight: 300,
  59.         //回调
  60.         renderCallBack: (e: Echarts) => {
  61.           this.myEchart = e
  62.           //初次渲染组件,接口获取数据是异步此时this.option可能还没有新数据
  63.           this.myEchart.render(this.option)
  64.         }
  65.       })
  66.     }
  67.     .width('100%')
  68.     .height('100%')
  69.   }
  70. }
复制代码
运行效果:


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

对于配置项包含函数的情况,比方坐标轴标签设置AxisLabel.formatter字段可以是个函数类型,此时就需要特殊处理。这是因为当我们通报option为对象给render函数时候
  1. this.controller.runJavaScript(`setOption(${typeof option === 'string' ? option : JSON.stringify(option)})`)
复制代码
此时调用JSON.stringify把对象转换为字符串,而JSON.stringify入参内函数会直接被去掉。
因此我们需要本身把option处理成字符串传入即可
代码示例:

给折线图y轴刻度值加个万字
Index.ets
  1. import Echarts from '../components/Echarts/Echarts'
  2. @Entry
  3. @Component
  4. struct Index {
  5.   //图表配置
  6.   @State option: string = ``
  7.   //x轴数据
  8.   @State xAxisData: string[] = [];
  9.   //y轴数据
  10.   @State seriesData: number[] = [];
  11.   myEchart: Echarts | null = null;
  12.   aboutToAppear(): void {
  13.     this.getData()
  14.   }
  15.   /*
  16.    * 设置配置并重新渲染
  17.    */
  18.   setOption() {
  19.     this.option = `{
  20.     title: {
  21.       text: '基础柱折线图'
  22.     },
  23.     grid:{
  24.       left:"15%"
  25.     },
  26.     legend:{
  27.       data: ['访问量']
  28.     },
  29.     xAxis: {
  30.       type: 'category',
  31.       data: ${JSON.stringify(this.xAxisData)}
  32.     },
  33.     yAxis: {
  34.       axisLabel: {
  35.         show: true,
  36.         formatter:(value, index)=> {
  37.             return value + '万';
  38.         }
  39.       }
  40.     },
  41.     series: [
  42.       {
  43.         data: ${JSON.stringify(this.seriesData)},
  44.         type: 'line',
  45.         name:'访问量'
  46.       }
  47.     ]
  48.   }`
  49.     this.myEchart?.render(this.option)
  50.   }
  51.   //接口请求获取数据
  52.   getData() {
  53.     //模拟接口请求
  54.     setTimeout(() => {
  55.       this.xAxisData = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  56.       this.seriesData = [120, 200, 150, 80, 70, 110, 130]
  57.       this.setOption()
  58.     }, 2000)
  59.   }
  60.   // 组件实例
  61.   chart?: Echarts;
  62.   build() {
  63.     Column() {
  64.         Echarts({
  65.           eHeight: 300,
  66.           renderCallBack: (e: Echarts) => {
  67.             this.myEchart = e
  68.             this.setOption()
  69.           }
  70.         })
  71.     }
  72.     .width('100%')
  73.     .height('100%')
  74.   }
  75. }
复制代码
运行效果:


总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南七星之家

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表