#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库 原创

无言de对话
发布于 2024-7-27 09:11
浏览
0收藏

前言

我自己之前想做一期关于chart 图表功能演示,我找了一圈下来 大致有 官方的@ohos/mpchart 但是使用习惯不是特别喜欢,因为自己以前经常用百度Echarts,虽然他的体积这些比较大,但是功能是真的非常强大,所以思索良久下定决心来基于Echarts封装一个自己的OpenHarmony三方库

准备工作

创建引入Static Library模块

1.创建 Static Library 模块。

这里需要注意是要鼠标移动到项目名称目录上,然后右键 创建新模块,然后选 Static Library 静态模块,模块名称命名自己可以随意,我这里用的是hm_chart。
#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

创建好模块之后的目录结构大致是这样的。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

2.在我们项目中引入 Static Library 模块。
  • 在项目 oh-package.json5 dependencies 中加载Static Library 模块文件,这里需要注意我们加了一个前缀@wuyan/ 这里可以加也不可以加,但是如果加了的化要记住名称,我们后面有用到。
{
  "name": "entry",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {
    "@wuyan/hm_chart": "file:../hm_chart"
  }
}

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

  • 打开终端 执行 ohpm install 命令。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

  • 在项目首页 src/main/ets/pages/Index.ets 文件中删掉之前没有用的代码引入模块。
import  {MainPage} from  "@wuyan/hm_chart"

@Entry
@Component
struct Index {
  build() {
    RelativeContainer() {
      MainPage();
    }
    .height('100%')
    .width('100%')
  }
}

打开右侧预览器 就可以看到如下页面。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

封装Echarts 插件

1.将从Echarts 官网定制化界面下载好的 echarts.js文件放入到 hm_chart 模块中 /src/main/ets/components 目录下面

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

2.新建 InitCharts.js 文件 放在和 echarts.js 同目录下面。


import * as echarts from './echarts';

export  class  InitCharts{
    constructor(ctx) {
     this.myChart = echarts.init(ctx); //初始化
    }
    // 绘制图表
    setOption(option){
        this.myChart.setOption(option)
    }
}

3.修改 MainPage.ets 文件绘制 canvas 并new InitCharts 初始化 eCharts。

import  {InitCharts} from "./InitCharts"

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

  build() {
      Column() {
        Canvas(this.context)
          .width('100%')
          .height('100%')
          .onReady(() => {
            const myChart = new InitCharts(this.context)
          })
      }
  }
}

让我们点击预览看看效果如何。好吧不出意外的报错了。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

4.打开 echarts.js 文件 全局搜索 this.dom.getContext('2d') 找到这行代码 去掉this.dom后面的.getContext('2d')

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

再试试预览效果,没报错了,离成功就很近了。

5.让我们来试一试 setOption 方法,官网上随便找了一段 option 配置,修改MainPage.ets 文件 加入 setOption 方法。

import  {InitCharts} from "./InitCharts"

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

  build() {
      Column() {
        Canvas(this.context)
          .width('100%')
          .height('100%')
          .onReady(() => {
            const myChart = new InitCharts(this.context) //初始化
            // 渲染图表
            myChart.setOption({
              title: {
                text: 'Stacked Line'
              },
              tooltip: {
                trigger: 'axis'
              },
              legend: {
                data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']
              },
              grid: {
                left: '3%',
                right: '4%',
                bottom: '3%',
                containLabel: true
              },
              xAxis: {
                type: 'category',
                boundaryGap: false,
                data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
              },
              yAxis: {
                type: 'value'
              },
              series: [
                {
                  name: 'Email',
                  type: 'line',
                  stack: 'Total',
                  data: [120, 132, 101, 134, 90, 230, 210]
                },
                {
                  name: 'Union Ads',
                  type: 'line',
                  stack: 'Total',
                  data: [220, 182, 191, 234, 290, 330, 310]
                },
                {
                  name: 'Video Ads',
                  type: 'line',
                  stack: 'Total',
                  data: [150, 232, 201, 154, 190, 330, 410]
                },
                {
                  name: 'Direct',
                  type: 'line',
                  stack: 'Total',
                  data: [320, 332, 301, 334, 390, 330, 320]
                },
                {
                  name: 'Search Engine',
                  type: 'line',
                  stack: 'Total',
                  data: [820, 932, 901, 934, 1290, 1330, 1320]
                }
              ]
            })
          })
      }
  }
}

非常完美,图表加载成功!
#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区
让我来点下看看,额… tooltip legend 的事件都相应丢失了,看看源码是怎么个回事呢? 原来是Echarts 底层用的 addEventListener 监听的事件,但是 HarmonyOS NEXT 是没有这个方法的。

网上找资料肯定是找不到了,看看Echarts官网有没有解决方案,终于我看到了 跨平台方案 里面有个微信适配,因为其实微信也是没有相关dom 的 addEventListener 事件的。从官网echarts-for-weixin链接点过去找到了wx-canvas.js 果然有适配方案。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

6.参照官网的思路,改造一下我们的 InitCharts.jsMainPage.ets

InitCharts.js 代码如下 添加了 onTouchEvent 绑定事件


import * as echarts from './echarts';

export  class  InitCharts{
    constructor(ctx) {
     this.myChart = echarts.init(ctx); //初始化
    }
    // 绘制图表
    setOption(option){
        this.myChart.setOption(option)
    }
    // 注册触摸事件
    onTouchEvent(event){
        const eventNames = [{
            type: '0',
            ecName: 'mousedown' //鼠标按下
        }, {
            type: '2',
            ecName: 'mousemove' //鼠标移动
        }, {
            type: '1',
            ecName: 'mouseup' // 鼠标离开
        }, {
            type: '1',
            ecName: 'click'
        }];
        eventNames.forEach(item => {
            if(event.type==item.type){
                const touch = event.touches[0];
                this.myChart.getZr().handler.dispatch(item.ecName, {
                    zrX: touch.x,
                    zrY: touch.y,
                    preventDefault: () => {},
                    stopImmediatePropagation: () => {},
                    stopPropagation: () => {}
                });
            }
        });
    }


}

MainPage.ets 代码如下 添加了 onTouch 事件


import  {InitCharts} from "./InitCharts"

@Component
export struct MainPage {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private  myChart:InitCharts|null = null

  build() {
      Column() {
        Canvas(this.context)
          .width('100%')
          .height('100%')
          .onReady(() => {
            this.myChart = new InitCharts(this.context)
            this.myChart.setOption({
              title: {
                text: 'Stacked Line'
              },
              tooltip: {
                trigger: 'axis'
              },
              legend: {
                data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']
              },
              grid: {
                left: '3%',
                right: '4%',
                bottom: '3%',
                containLabel: true
              },
              xAxis: {
                type: 'category',
                boundaryGap: false,
                data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
              },
              yAxis: {
                type: 'value'
              },
              series: [
                {
                  name: 'Email',
                  type: 'line',
                  stack: 'Total',
                  data: [120, 132, 101, 134, 90, 230, 210]
                },
                {
                  name: 'Union Ads',
                  type: 'line',
                  stack: 'Total',
                  data: [220, 182, 191, 234, 290, 330, 310]
                },
                {
                  name: 'Video Ads',
                  type: 'line',
                  stack: 'Total',
                  data: [150, 232, 201, 154, 190, 330, 410]
                },
                {
                  name: 'Direct',
                  type: 'line',
                  stack: 'Total',
                  data: [320, 332, 301, 334, 390, 330, 320]
                },
                {
                  name: 'Search Engine',
                  type: 'line',
                  stack: 'Total',
                  data: [820, 932, 901, 934, 1290, 1330, 1320]
                }
              ]
            })
          })
          .onTouch((event: TouchEvent)=>{
            if(this.myChart){
              this.myChart.onTouchEvent(event)
            }
          })

      }
  }
}

看看效果 legend 事件生效了, 但是 tooltip 还是没有反应。
#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

经过分析发现是 echarts.js 源码中 Env 环境判断错误 导致识别成 node 服务器环境了。

7.打开 echarts.js 源码 搜索 new Env() 注释掉 env.node = true; env.svgSupported = true; 搜索 addEventListener 注释掉 el.addEventListener(name, handler, opt);el.removeEventListener(name, handler, opt);

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区
最后再预览一下 看看效果。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

打包发布插件

{
  "name": "@wuyan/hm_chart",
  "version": "1.0.0",
  "keywords":["chart","echarts","hm_chart"],
  "description": "一个基于echarts 进行二次封装的插件,基本上完全支持echarts 的所有功能。",
  "main": "Index.ets",
  "author": "wuyan",
  "license": "Apache-2.0",
  ohos: {
    org: 'wuyan',
  },
  "dependencies": {}
}
  • 打开命令生成OHPM 公钥

说明 官方是 ~/.ssh_ohpm/mykey 我觉得反而不好理解,我这里直接用mykey 就是私钥的名称。
需要注意的是必须输入密码,这样在后续发布HAR包的时候有用到。

ssh-keygen -m PEM -t RSA -b 4096 -f mykey 

执行成功后

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

需要注意的是用系统自带的窗口执行可能会报错 ohpm 无法识别,所以推荐直接用我们开发工具的终端执行命令,后续发布HAR 包也是一样。

ohpm config set key_path E:\work\test\MyApplication\mykey

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

ohpm config set publish_id your-publishId
  • 在我们之前创建的静态模块跟目录下创建 README.md(描述信息),CHANGELOG.md(更新日志) 和 LICENSE(开源协议license) 四个文件,若文件缺失,内容缺少,内容必须真实,会导致上架至中心仓失败(有人工审核)

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

  • 对开发后的库模块打成 HAR 包、发布HAR包。
    打包
    #HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区
    发布包 <HAR路径> 等于你包文件的实际路径 我这里是 E:\work\test\MyApplication\hm_chart\build\default\outputs\default\hm_chart.har自己要根据自己实际项目情况修改。
ohpm publish <HAR路径>

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

详细教程可以参考官网帮助文档 里面介绍非常详细 认证管理贡献三方库

总结

本篇文章详细介绍了如何创建一个 OpenHarmony三方库 , 以及如何对Echarts 进行封装,在封装过程中出现的错误,进行思考调整,希望对你们后面创建自己的 OpenHarmony三方库 有所帮助,如果有问题欢迎评论区见。
最后我把代码进行整理并开源放在了gitee 上,有需要的可以下载下来研究研究。

创作不易,觉得本篇文章不错的留下一个赞呗。

问题更新

经过掘友@lwlizhe 提醒在模拟器上会报错global is not defined,我的处理方案是在var root =这行代码前面加上global定义var global={}即可解决问题。

#HarmonyOS NEXT体验官#(基于Echarts)开发一个OpenHarmony三方库-鸿蒙开发者社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2024-8-4 12:31:21修改
收藏
回复
举报
回复
    相关推荐