当前位置: 首页 > 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大小。

相关文章:

uniapp echarts 适配H5与微信小程序

文章目录 前言一、修改 ec-canvas组件1.1 在ec-canvas组件methods中定义一个initChart方法1.2 用initChart全局替换this.ec.onInit1.3 监听数据变化1.4 ec-canvas完整代码参考 二、H5 echarts组件三、供外部调用的组件外部调用组件 uni-chart代码使用uni-chart 前言 接上文&…...

第46节——redux中使用不可变数据+封装immer中间件——了解

一、为什么redux中要使用不可变数据 Redux 要求使用不可变数据&#xff0c;是因为它遵循了函数式编程的原则。在函数式编程中&#xff0c;数据不可变是一项重要的原则&#xff0c;这有助于避免状态更改产生的不可预知的副作用。 在 Redux 中&#xff0c;每当 action 被分发&a…...

《数字图像处理-OpenCV/Python》连载(10)图像属性与数据类型

《数字图像处理-OpenCV/Python》连载&#xff08;10&#xff09;图像属性与数据类型 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第2章 图像的数据格式 在P…...

sheng的学习笔记-【中文】【吴恩达课后测验】Course 2 - 改善深层神经网络 - 第三周测验

课程2_第3周_测验题 目录&#xff1a;目录 第一题 1.如果在大量的超参数中搜索最佳的参数值&#xff0c;那么应该尝试在网格中搜索而不是使用随机值&#xff0c;以便更系统的搜索&#xff0c;而不是依靠运气&#xff0c;请问这句话是正确的吗&#xff1f; A. 【  】对 B.…...

LLMs 用强化学习进行微调 RLHF: Fine-tuning with reinforcement learning

让我们把一切都整合在一起&#xff0c;看看您将如何在强化学习过程中使用奖励模型来更新LLM的权重&#xff0c;并生成与人对齐的模型。请记住&#xff0c;您希望从已经在您感兴趣的任务上表现良好的模型开始。您将努力使指导发现您的LLM对齐。首先&#xff0c;您将从提示数据集…...

iMazing 2.17.10官方中文版含2023最新激活许可证码

iMazing 2.17.10官方中文版是一款iOS设备管理软件&#xff0c;该软件支持对基于iOS系统的设备进行数据传输与备份&#xff0c;用户可以将包括&#xff1a;照片、音乐、铃声、视频、电子书及通讯录等在内的众多信息在Windows/Mac电脑中传输/备份/管理。 iMazing 2.17.10官方中文…...

如何在windows系统环境下使用tail命令查看日志

答案是&#xff1a; 使用tail for Windows工具 tail for Windows 是便携式软件不需要安装&#xff0c;它可用于显示文件的最后一行并跟踪/监视文件的更改。 下载地址&#xff1a; https://tail-for-windows.en.softonic.com/ 点击直接下载 解压使用 解压后需将tail.exe放入 c:…...

设计模式——访问者模式

访问者模式是什么&#xff1f; 表示一个作用于某对象结构中的各元素的操作&#xff0c;它使你可以再不改变各元素的类的前提下定义作用于这些元素的新操作 访问者模式解决什么问题&#xff1f; 男女在不同情境下表现的不同 abstract class Person {protected String action…...

一文读懂UTF-8的编码规则

之前写过一篇文章“一文彻底搞懂计算机中文编码”里面只是介绍了GB2312编码知识&#xff0c;关于utf8没有涉及到&#xff0c;经过查询资料发现utf8是对unicode的一种可变长度字符编码&#xff0c;所以再记录一下。 现在国家对于信息技术中文编码字符集制定的标准是《GB 18030-…...

二叉树题目:路径总和 II

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;路径总和 II 出处&#xff1a;113. 路径总和 II 难度 4 级 题目描述 要求 给你二叉树的根结点 root \tex…...

Qt model/view 理解01

在 Qt 中对数据处理主要有两种方式&#xff1a;1&#xff09;直接对包含数据的的数据项 item 进行操作&#xff0c;这种方法简单、易操作&#xff0c;现实方式单一的缺点&#xff0c;特别是对于大数据或在不同位置重复出现的数据必须依次对其进行操作&#xff0c;如果现实方式改…...

c与c++中的字符串

在c中&#xff0c;string本质上是一个类&#xff1b; string与char *有些区别&#xff1a; char*是一个指针&#xff1b;string是一个类&#xff0c;类内封装了char*&#xff0c;管理这一个字符串&#xff0c;是一个char*的容器 在使用string类型时&#xff0c;要加上其头文…...

Android 获取IP地址的Ping值 NetworkPingUtils

项目里需要对动态配置的Ip列表都去ping下延迟&#xff0c;取出其中最小的三个进行随机取值然后去连接&#xff0c;倒腾了一下午终于搞出来了&#xff01; 需求实现思路&#xff1a; 1.找到方法去ping IP地址&#xff1b; 2.同时去Ping&#xff0c;不能让用户等待&#xff1b…...

数据集笔记:OpenCelliD(手机基站开放数据库)

下载数据的方式可见&#xff1a;【数据获取】全球最大手机基站开源数据库 1 读取数据 import pandas as pdpd.read_csv(C:/Users/16000/Downloads/454.csv/454.csv,headerNone,names[radio,mcc,net,area,cell,unit,lon,lat,range,samples,changeable1,created1,updated,AveSi…...

Windows电脑多开器的使用心得分享

Windows电脑多开器是一种非常实用的软件工具&#xff0c;它可以让我们在同一个电脑上同时运行多个不同的应用程序&#xff0c;从而提高我们的工作和学习效率。以下是我在使用Windows电脑多开器时的一些心得分享&#xff1a; 确保你的电脑配置足够强大 多开软件需要消耗大量的…...

Android Studio实现简易计算器(带横竖屏,深色浅色模式,更该按钮颜色,selector,style的使用)

目录 前言 运行结果&#xff1a; 运行截屏&#xff08;p50e&#xff09; apk文件 源码文件 项目结构 总览 MainActivity.java drawable 更改图标的方法&#xff1a; blackbutton.xml bluebuttons.xml greybutton.xml orangebuttons.xml whitebutton.xml layout 布…...

虚拟机通过nat模式端口映射实现内网穿透

虚拟机通过nat模式端口映射实现内网穿透 1.网络状态 windows虚拟主机的IP为局域网的私有IP192.168.1.7linux的虚拟主机IP为nat的172.36.4.1062.linux修改nat模式的端口映射 3.windows宿主机防火墙添加规则,&#xff08;或者直接关闭公共网络防火墙&#xff0c;不安全&#xf…...

计算机网络(六):应用层

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 应用层概述 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分 早期基于文本的应用 (电子邮件、远程登…...

Sublime Text 4 for Mac激活下载

Sublime Text for Mac是一款适用于Mac平台的文本编辑器。它具有快速的性能和丰富的功能&#xff0c;可以帮助用户快速进行代码编写和文本编辑。 软件下载&#xff1a;Sublime Text 4 for Mac激活下载 该软件具有直观的界面和强大的功能&#xff0c;包括多行选择、代码折叠、自动…...

存在负权边的单源最短路径的原理和C++实现

负权图 此图用朴素迪氏或堆优化迪氏都会出错&#xff0c;floyd可以处理。 负环图 但floyd无法处理负权环&#xff0c;最短距离是无穷小。在环上不断循环。 经过k条边的最短距离&#xff08;可能有负权变&#xff09; 贝尔曼福特算法(bellman_ford)就是解决此问题的。 原理 …...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...