Taro引入echarts【兼容多端小程序(飞书/微信/支付宝小程序)】

近期接到公司新需求,开发飞书小程序,并且原型中含有大量的图表,本想使用飞书内置图表组件 ——
chart-space,但官方表示已经停止维护了,无奈之下,只能另寻他路,于是乎,图表之王(文档最完整,api最透彻,社区最活跃)echarts映入我脑海中,决定就是你了!

下载echarts代码

进入echarts下载地址,点击在线定制
在这里插入图片描述
勾选你需要的图表和组件,点击下载在这里插入图片描述
在这里插入图片描述

echarts引入项目

在开发项目中,components中创建Echarts文件,放入下载后的js包,并在该目录下创建wx-canvas.js,编写canvas构造函数代码,如下

export default class WxCanvas {constructor(ctx, canvasId, isNew, canvasNode) {this.ctx = ctx;this.canvasId = canvasId;this.chart = null;this.isNew = isNewif (isNew) {this.canvasNode = canvasNode;}else {this._initStyle(ctx);}// this._initCanvas(zrender, ctx);this._initEvent();}getContext(contextType) {if (contextType === '2d') {return this.ctx;}}// canvasToTempFilePath(opt) {//   if (!opt.canvasId) {//     opt.canvasId = this.canvasId;//   }//   return wx.canvasToTempFilePath(opt, this);// }setChart(chart) {this.chart = chart;}addEventListener() {// noop}attachEvent() {// noop}detachEvent() {// noop}_initCanvas(zrender, ctx) {zrender.util.getContext = function () {return ctx;};zrender.util.$override('measureText', function (text, font) {ctx.font = font || '12px sans-serif';return ctx.measureText(text);});}_initStyle(ctx) {ctx.createRadialGradient = () => {return ctx.createCircularGradient(arguments);};}_initEvent() {this.event = {};const eventNames = [{wxName: 'touchStart',ecName: 'mousedown'}, {wxName: 'touchMove',ecName: 'mousemove'}, {wxName: 'touchEnd',ecName: 'mouseup'}, {wxName: 'touchEnd',ecName: 'click'}];eventNames.forEach(name => {this.event[name.wxName] = e => {const touch = e.touches[0];this.chart.getZr().handler.dispatch(name.ecName, {zrX: name.wxName === 'tap' ? touch.clientX : touch.x,zrY: name.wxName === 'tap' ? touch.clientY : touch.y,preventDefault: () => {},stopImmediatePropagation: () => {},stopPropagation: () => {}});};});}set width(w) {if (this.canvasNode) this.canvasNode.width = w}set height(h) {if (this.canvasNode) this.canvasNode.height = h}get width() {if (this.canvasNode)return this.canvasNode.widthreturn 0}get height() {if (this.canvasNode)return this.canvasNode.heightreturn 0}
}

目录结构如下图
在这里插入图片描述
在Echarts文件中,创建ec-canvas.vue文件,创建canvas对象

<template><!--  // 多个echarts时将canvasId作为唯一标识,动态获取canvasId用于多个echarts可同时显示    --><canvastype="2d"class="ec-canvas":id="canvasId":canvas-id="canvasId"@touchStart="touchStart"@touchMove="touchMove"@touchEnd="touchEnd"></canvas>
</template><script lang="js">
import Taro from "@tarojs/taro";
import WxCanvas from "@/components/Echarts/wx-canvas";
import * as echarts from "@/components/Echarts/echarts.min";export default {name: "EcCanvas",props: {canvasId: {type: String,default: "",},chartData: {type: Array,default: () => [],},option: {type: Object,default: () => {}}},data() {return {}},watch: {chartData: function() {console.log('chartData', this.chartData)this.handleCreate()},},mounted() {echarts.registerPreprocessor(option => {if (option && option.series) {if (option.series.length > 0) {option.series.forEach(series => {series.progressive = 0;});} else if (typeof option.series === "object") {option.series.progressive = 0;}}})},methods: {init(callback) {this.initByNewWay(callback);},// eslint-disable-next-line complexityhandleCreate() {const option = this.optionconst v = thisv.init((canvas, width, height, canvasDpr) => {const chart = echarts.init(canvas, null, {width: width,height: height,devicePixelRatio: canvasDpr,})canvas.setChart(chart);chart.setOption(option);chart.on('click', (params) => {console.log('params', params)this.$emit('clickEChartItem', params)});return chart;})},initByNewWay(callback) {const query = Taro.createSelectorQuery();query.select(`#${this.canvasId}`) // 根据canvasId动态获取不同的echarts图表.fields({// node: true, // 飞书里面没有nodedataset: true,size: true,})// eslint-disable-next-line complexity.exec(res => {console.log('query res', res)// eslint-disable-next-line eqeqeq// if (!res || res.length == 0 || res[0] == null || res[0].node == null) {//   console.error('未获取到canvas的dom节点,请确认在页面渲染完成后或节点,taro中页面渲染完成的生命周期是useReady');//   return// }// const canvasNode = res[0].node;// this.canvasNode = canvasNode;console.log(11,this.option.height);const canvasDpr = Taro.getSystemInfoSync().pixelRatio;const canvasWidth = res[0].width;const canvasHeight = res[0].height;// const ctx = canvasNode.getContext("2d");const ctx = tt.createCanvasContext(this.canvasId)console.log('ctx', ctx)// const canvas = new WxCanvas(ctx, this.canvasId, true, canvasNode) // 不给canvasNode也可以const canvas = new WxCanvas(ctx, this.canvasId, true);echarts.setCanvasCreator(() => {return canvas;});this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)});},touchStart(e) {if (this.chart && e.touches.length > 0) {var touch = e.touches[0];var handler = this.chart.getZr().handler;handler.dispatch("mousedown", {zrX: touch.x,zrY: touch.y,});handler.dispatch("mousemove", {zrX: touch.x,zrY: touch.y,});handler.processGesture(this.wrapTouch(e), "start");}},touchMove(e) {if (this.chart && e.touches.length > 0) {var touch = e.touches[0];var handler = this.chart.getZr().handler;handler.dispatch("mousemove", {zrX: touch.x,zrY: touch.y,});handler.processGesture(this.wrapTouch(e), "change");}},touchEnd(e) {if (this.chart) {const touch = e.changedTouches ? e.changedTouches[0] : {};var handler = this.chart.getZr().handler;handler.dispatch("mouseup", {zrX: touch.x,zrY: touch.y,});handler.dispatch("click", {zrX: touch.x,zrY: touch.y,});handler.processGesture(this.wrapTouch(e), "end");}},wrapTouch(event) {for (let i = 0; i < event.touches.length; ++i) {const touch = event.touches[i];touch.offsetX = touch.x;touch.offsetY = touch.y;}return event;},},
};
</script><style>
.ec-canvas {width: 100%;height: 100%;min-height: 208px;flex: 1;
}
</style>

二次封装echarts组件

使用创建的echart组件,稍微进行二次封装,大佬可以用自己的方法封装更好的,我的思路是,页面只要给echarts传入不同option,就可以进行渲染,代码如下:

// eChart.vue
<template><EcCanvas :ref="canvasId" :canvasId="canvasId" :option="option"></EcCanvas>
</template><script>
import EcCanvas from './ec-canvas.vue'
import { watch, ref, toRefs } from 'vue'export default {components: {EcCanvas,},props: {canvasId: {type: String,default: () => '',},option: {type: Object,default: () => {},},},watch: {option: {handler(value) {this.$nextTick(() => { // 没有下一帧会出现无法渲染的问题 页面没有挂载完成this.$refs[this.canvasId] && this.$refs[this.canvasId].handleCreate()})},deep: true,},},
}
</script><style lang="scss">
</style>

使用echarts组件渲染页面

<template>
<view class="chart"><e-chart canvasId="canvasId" :option="option"></e-chart></view></template><script>import eChart from '@/componets/Echart/eChart.vue'import { reactive}  from 'vue'export default {components: { eChart },setup() {const state =  reactive({option: {}})onMounted(async () => {// 模拟在挂载后,进行数据请求,这边我直接对option赋值// 数据来源于echarts官方实例中,最基础的柱状图state.option = {xAxis: {type: 'category',data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']},yAxis: {type: 'value'},series: [{data: [120, 200, 150, 80, 70, 110, 130],type: 'bar'}]}})return {...toRefs(state),}}
}</script>
<style>
.chart {width: 100%;height: 300px;}
</style>

数据与图不符
最后,需要进行各种各样的渲染与修改,可直接参看echarts官网
希望此文对大家有帮助,也请大佬不吝赐教~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/661048.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 脚手架 创建vue3项目

创建项目 命令&#xff1a;vue create vue-element-plus 选择配置模式&#xff1a;手动选择模式 (上下键回车) 选择配置&#xff08;上下键空格回车&#xff09; 选择代码规范、规则检查和格式化方式: 选择语法检查方式 lint on save (保存就检查) 代码文件中有代码不符合 l…

TiDB系列之:部署TiDB集群常见报错解决方法

TiDB系列之&#xff1a;部署TiDB集群常见报错解决方法 一、部署TiDB集群二、unsupported filesystem ext3三、soft limit of nofile四、THP is enabled五、numactl not usable六、net.ipv4.tcp_syncookies 1七、service irqbalance not found,八、登陆TiDB数据库 一、部署TiDB…

aardio - 用 customPlus 轻松制作九宫格效果

import win.ui; /*DSG{{*/ var mainForm win.form(text"数独";right599;bottom599;maxfalse) mainForm.add( plus{cls"plus";left8;top8;right553;bottom559;notify1;z1}; ) /*}}*///定义模板 itemModel {} for(x1;3;1){for(y1;3;1){ /*每个项目的9宫格*…

【AIGC调研系列】InternVL开源多模态模型与GPT-4V的性能对比

InternVL和GPT-4V都是多模态模型&#xff0c;但它们在性能、参数量以及应用领域上有所不同。 InternVL是一个开源的多模态模型&#xff0c;其参数量为60亿&#xff0c;覆盖了图像/视频分类、检索等关键任务&#xff0c;并在32个视觉-语言基准测试中展现了卓越性能[2]。InternV…

Vue通过下拉框选择字典值,并将对应的label以及value值提交到后端

产品品种从字典中获取 产品性质也是从字典中获取 字典当中的保存 dict_type表 dict_data表 在表单提交的方法中 1.因为做的产品性质是多选&#xff0c;它会以数组的方式提交&#xff0c;所以需要先将Json格式转变为String JSON.stringify(this.form.nature) 2.提交表单&…

Flutter笔记:Widgets Easier组件库(1)使用各式边框

Flutter笔记 Widgets Easier组件库&#xff08;1&#xff09;&#xff1a;使用边框 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

java-springmvc 01 补充 javaweb 三大组件Servlet,Filter、Listener(源码都是tomcat8.5项目中的)

01.JavaWeb三大组件指的是&#xff1a;Servlet、Filter、Listener,三者提供不同的功能 这三个在springmvc 运用很多 Servlet 01.Servlet接口&#xff1a; public interface Servlet {/*** 初始化方法* 实例化servlet之后&#xff0c;该方法仅调用一次 * init方法必须执行完…

华为5700配置

恢复出厂设置&#xff0c;清空配置 1、更改名字 system-view sysname tp-10-50-01-04 2、配置管理接口 int vlan 1 ip add 10.50.1.4 255.255.254.0 quit 2、链路汇聚 interface eth-trunk 1 mode lacp quit 3、绑定端口 interface eth-trunk 1 trunkport gigabitethernet …

C语言-嵌入式-STM32:FreeRTOS说明和详解

Free即免费的&#xff0c;RTOS的全称是Real time operating system&#xff0c;中文就是实时操作系统。 注意&#xff1a;RTOS不是指某一个确定的系统&#xff0c;而是指一类操作系统。比如&#xff1a;uc/OS&#xff0c;FreeRTOS&#xff0c;RTX&#xff0c;RT-Thread 等这些都…

【语音识别】搭建本地的语音转文字系统:FunASR(离线不联网即可使用)

参考自&#xff1a; 参考配置&#xff1a;FunASR/runtime/docs/SDK_advanced_guide_offline_zh.md at main alibaba-damo-academy/FunASR (github.com)参考配置&#xff1a;FunASR/runtime/quick_start_zh.md at 861147c7308b91068ffa02724fdf74ee623a909e alibaba-damo-aca…

动手学深度学习——softmax分类

1. 分类问题 回归与分类的区别&#xff1a; 回归可以用于预测多少的问题&#xff0c; 比如"预测房屋被售出价格"&#xff0c;它是个单值输出。softmax可以用来预测分类问题&#xff0c;例如"某个图片中是猫、鸡还是狗&#xff1f;"&#xff0c;这是一个多…

鸿蒙准备1

鸿蒙心路 感慨索性&#xff0c; 看看鸿蒙吧。打开官网相关介绍 新建工程目录结构 感慨 最近面试Android应用开发&#xff0c;动不动就问framework的知识&#xff0c;什么touch事件的触发源是啥&#xff08;eventHub&#xff09;&#xff0c;gc流程是啥&#xff0c;图形框架是什…