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