当前位置: 首页 > news >正文

uniapp echarts 适配H5与微信小程序

文章目录

  • 前言
  • 一、修改 ec-canvas组件
      • 1.1 在`ec-canvas`组件methods中定义一个`initChart`方法
      • 1.2 用initChart全局替换this.ec.onInit
      • 1.3 监听数据变化
      • 1.4 ec-canvas完整代码参考
  • 二、H5 echarts组件
  • 三、供外部调用的组件
      • 外部调用组件 uni-chart代码
      • 使用uni-chart


前言

接上文:uniapp 微信小程序使用echarts,这篇文章目的为使用uniapp时提供一个同时兼容H5和小程序的echarts组件,在使用时尽量减少心智负担。


一、修改 ec-canvas组件


首先修改uniapp 微信小程序使用echarts中的ec-canvas组件,将initChart方法置于该组件内部,而不是存在于业务组件中。

1.1 在ec-canvas组件methods中定义一个initChart方法

export default {initChart(canvas, width, height, dpr) {const chartInstance = echarts.init(canvas, null, {width,height,devicePixelRatio: dpr // 像素})canvas.setChart(this.chartInstance)chartInstance.setOption(this.ec.option || {})return chartInstance}
}

1.2 用initChart全局替换this.ec.onInit

  • 修改initByOldWayinitByNewWay两个方法
methods: {initByOldWay(callback) {//...其余逻辑else if ( this.ec ) {this.chart = this.initChart(canvas,res.width,res.height,canvasDpr)}//...其余逻辑},initByNewWay(callback) {//...其余逻辑else if (this.ec) {this.chart = this.initChart(canvas,canvasWidth,canvasHeight,canvasDpr)}//...其余逻辑}
}

1.3 监听数据变化

  • 阅读initChart方法,可知我们现在的图表数据是从props中的ec来的,ec是个对象,有一个option的键。对这个option监听即可:

注:这里没必要使用深度监听,外部组件使用时,如果图表数据的值有变化,直接将有变化的部分直接赋值给option即可,而不是通过option.xxx去修改数据。
如果想要通过option.xxx去修改数据,那么就需要深度监听了。

export default {//...其余代码watch: {"ec.option"(val) {if(!this.chart) returnthis.chart.setOption(val)}},//...其余代码
}

1.4 ec-canvas完整代码参考

<template><uni-shadow-root class="ec-canvas-ec-canvas"><canvasv-if="isUseNewCanvas"type="2d"class="ec-canvas":canvas-id="canvasId"@init="init"@touchstart="touchStart"@touchmove="touchMove"@touchend="touchEnd"></canvas><canvasv-elseclass="ec-canvas":canvas-id="canvasId"@init="init"@touchstart="touchStart"@touchmove="touchMove"@touchend="touchEnd"></canvas></uni-shadow-root>
</template><script>
import WxCanvas from './wx-canvas'
import * as echarts from './echarts.min.js'let ctxfunction compareVersion(v1, v2) {v1 = v1.split('.')v2 = v2.split('.')const len = Math.max(v1.length, v2.length)while (v1.length < len) {v1.push('0')}while (v2.length < len) {v2.push('0')}for (let i = 0; i < len; i++) {const num1 = parseInt(v1[i])const num2 = parseInt(v2[i])if (num1 > num2) {return 1} else if (num1 < num2) {return -1}}return 0
}function wrapTouch(event) {for (let i = 0; i < event.touches.length; ++i) {const touch = event.touches[i]touch.offsetX = touch.xtouch.offsetY = touch.y}return event
}
export default {props: {canvasId: {type: String,value: 'ec-canvas',},ec: {type: Object,},forceUseOldCanvas: {type: Boolean,value: false,},},data() {return {isUseNewCanvas: false,}},watch: {"ec.option"(val) {if(!this.chart) returnthis.chart.setOption(val)}},onReady: function () {// Disable prograssive because drawImage doesn't support DOM as parameter// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.htmlecharts.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}}})if (!this.ec) {console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" ' +'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>')return}if (!this.ec.lazyLoad) {this.init()}},methods: {init: async function (callback) {const version = wx.getSystemInfoSync().SDKVersionconst canUseNewCanvas = compareVersion(version, '2.9.0') >= 0const forceUseOldCanvas = this.forceUseOldCanvasconst isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvasthis.isUseNewCanvas = isUseNewCanvasif (forceUseOldCanvas && canUseNewCanvas) {console.warn('开发者强制使用旧canvas,建议关闭')}await this.$nextTick()if (isUseNewCanvas) {// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');// 2.9.0 可以使用 <canvas type="2d"></canvas>this.initByNewWay(callback)} else {const isValid = compareVersion(version, '1.9.91') >= 0if (!isValid) {console.error('微信基础库版本过低,需大于等于 1.9.91。' +'参见:https://github.com/ecomfe/echarts-for-weixin' +'#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82')return} else {console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能')this.initByOldWay(callback)}}},initChart(canvas, width, height, dpr) {const chartInstance = echarts.init(canvas, null, {width,height,devicePixelRatio: dpr // 像素})canvas.setChart(this.chartInstance)chartInstance.setOption(this.ec.option || {})return chartInstance},initByOldWay(callback) {// 1.9.91 <= version < 2.9.0:原来的方式初始化ctx = wx.createCanvasContext(this.canvasId, this)const canvas = new WxCanvas(ctx, this.canvasId, false)echarts.setCanvasCreator(() => {return canvas})// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dprconst canvasDpr = 1var query = wx.createSelectorQuery().in(this)query.select('.ec-canvas').boundingClientRect((res) => {if (typeof callback === 'function') {this.chart = callback(canvas, res.width, res.height, canvasDpr)} else if ( this.ec ) {this.chart = this.initChart(canvas,res.width,res.height,canvasDpr)} else {this.triggerEvent('init', {canvas: canvas,width: res.width,height: res.height,canvasDpr: canvasDpr, // 增加了dpr,可方便外面echarts.init})}}).exec()},initByNewWay(callback) {// version >= 2.9.0:使用新的方式初始化const query = wx.createSelectorQuery().in(this)query.select('.ec-canvas').fields({ node: true, size: true }).exec((res) => {const canvasNode = res[0].nodethis.canvasNode = canvasNodeconst canvasDpr = wx.getSystemInfoSync().pixelRatioconst canvasWidth = res[0].widthconst canvasHeight = res[0].heightconst ctx = canvasNode.getContext('2d')const canvas = new WxCanvas(ctx, this.canvasId, true, canvasNode)echarts.setCanvasCreator(() => {return canvas})if (typeof callback === 'function') {this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)} else if (this.ec) {this.chart = this.initChart(canvas,canvasWidth,canvasHeight,canvasDpr)} else {this.triggerEvent('init', {canvas: canvas,width: canvasWidth,height: canvasHeight,dpr: canvasDpr,})}})},canvasToTempFilePath(opt) {if (this.isUseNewCanvas) {// 新版const query = wx.createSelectorQuery().in(this)query.select('.ec-canvas').fields({ node: true, size: true }).exec((res) => {const canvasNode = res[0].nodeopt.canvas = canvasNodewx.canvasToTempFilePath(opt)})} else {// 旧的if (!opt.canvasId) {opt.canvasId = this.canvasId}ctx.draw(true, () => {wx.canvasToTempFilePath(opt, this)})}},touchStart(e) {if (this.chart && e.touches.length > 0) {var touch = e.touches[0]var handler = this.chart.getZr().handlerhandler.dispatch('mousedown', {zrX: touch.x,zrY: touch.y,preventDefault: () => {},stopImmediatePropagation: () => {},stopPropagation: () => {},})handler.dispatch('mousemove', {zrX: touch.x,zrY: touch.y,preventDefault: () => {},stopImmediatePropagation: () => {},stopPropagation: () => {},})handler.processGesture(wrapTouch(e), 'start')}},touchMove(e) {if (this.chart && e.touches.length > 0) {var touch = e.touches[0]var handler = this.chart.getZr().handlerhandler.dispatch('mousemove', {zrX: touch.x,zrY: touch.y,preventDefault: () => {},stopImmediatePropagation: () => {},stopPropagation: () => {},})handler.processGesture(wrapTouch(e), 'change')}},touchEnd(e) {if (this.chart) {const touch = e.changedTouches ? e.changedTouches[0] : {}var handler = this.chart.getZr().handlerhandler.dispatch('mouseup', {zrX: touch.x,zrY: touch.y,preventDefault: () => {},stopImmediatePropagation: () => {},stopPropagation: () => {},})handler.dispatch('click', {zrX: touch.x,zrY: touch.y,preventDefault: () => {},stopImmediatePropagation: () => {},stopPropagation: () => {},})handler.processGesture(wrapTouch(e), 'end')}},},
}
</script>
<style scoped>
.ec-canvas {width: 100%;height: 100%;
}
</style>

二、H5 echarts组件


  • 其实就是平时正常使用echarts,取名为ec-h5,直接上代码:
<template><view class="h5-chart-container" :id="id"></view>
</template><script>import * as echarts from './echarts.min.js'export default {props: {id: {type: String,default: 'ec-h5-id'},option: {type: Object,default: () => {}}},watch: {option(val) {if(!this.chart) returnthis.chart.setOption(val)}},data() {return {}},mounted() {this.initChart()},methods: {initChart() {const chartDom = document.getElementById(this.id)this.chart = echarts.init(chartDom)this.chart.setOption(this.option)}}}
</script><style scoped>
.h5-chart-container {height: 100%;width: 100%;
}
</style>

三、供外部调用的组件


外部调用组件 uni-chart代码

  • 取名为uni-chart,通过条件编译的方式,由这个组件判断是微信还是H5。
<template><!--  #ifdef  MP-WEIXIN --><ec-canvas :ec="{option}" :canvasId="id" /><!--  #endif --><!--  #ifdef  H5 --><ec-h5 :option="option" :id="id" /><!--  #endif -->
</template><script>import ecCanvas from './ec-canvas.vue';import ecH5 from './ec-h5.vue'export default {props: {id: {type: String,default: 'uni-chart-id'},option: {type: Object,default: () => {}}},components: {ecCanvas,ecH5},}
</script>

使用uni-chart

  • 参考:
<template><view class="parent-container"><uni-chart class="my-chart" :option="option" /></view>
</template><script>
import uniChart from './components/uni-chart.vue'
export default {components: {uniChart,},data() {return {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',},],},}},mounted() {// 动态更新图表数据setTimeout(() => {this.option = {series: [{data: [12, 20, 15, 8, 7, 11, 13],color: ['red']},],}}, 2000)},
}
</script>
<style scoped>
.parent-container {height: 100vh;
}
.my-chart {height: 600rpx;
}
</style>

碎碎念:微信小程序主包限制有2MB,所以这个组件不好放于根目录下的components,这样会被打到主包里,所以创个分包,将图表相关的业务组件都丢到这个分包去,这样最好。
分包也能有static文件夹,但是我丢进去之后,uni还是会重复打包,导致分包什么都没有,就有2MB大小。

http://www.lryc.cn/news/182506.html

相关文章:

  • 第46节——redux中使用不可变数据+封装immer中间件——了解
  • 《数字图像处理-OpenCV/Python》连载(10)图像属性与数据类型
  • sheng的学习笔记-【中文】【吴恩达课后测验】Course 2 - 改善深层神经网络 - 第三周测验
  • LLMs 用强化学习进行微调 RLHF: Fine-tuning with reinforcement learning
  • iMazing 2.17.10官方中文版含2023最新激活许可证码
  • 如何在windows系统环境下使用tail命令查看日志
  • 设计模式——访问者模式
  • 一文读懂UTF-8的编码规则
  • 二叉树题目:路径总和 II
  • Qt model/view 理解01
  • c与c++中的字符串
  • Android 获取IP地址的Ping值 NetworkPingUtils
  • 数据集笔记:OpenCelliD(手机基站开放数据库)
  • Windows电脑多开器的使用心得分享
  • Android Studio实现简易计算器(带横竖屏,深色浅色模式,更该按钮颜色,selector,style的使用)
  • 虚拟机通过nat模式端口映射实现内网穿透
  • 计算机网络(六):应用层
  • Sublime Text 4 for Mac激活下载
  • 存在负权边的单源最短路径的原理和C++实现
  • 15-自动化测试——理论知识
  • 学信息系统项目管理师第4版系列17_干系人管理
  • 专业PDF编辑阅读工具PDF Expert mac中文特点介绍
  • 处理机调度的概念,层次联系以及七状态模型
  • PS 图层剪贴蒙版使用方法
  • 总结1008
  • 软件工程从理论到实践客观题汇总(头歌第九章至第十七章)
  • ubuntu与win之间共享文件夹
  • flink处理函数--副输出功能
  • Java数据结构————队列
  • 办公网络构建