历史温度暂时提交
parent
3583296329
commit
72a71589b4
2
App.vue
2
App.vue
|
|
@ -218,6 +218,6 @@ export default {
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
// 加上图鸟会全变白
|
// 加上图鸟会全变白
|
||||||
@import './tuniao-ui/iconfont.css';
|
//@import './tuniao-ui/iconfont.css'; // 去掉main.wxss少一半
|
||||||
@import '@/static/scss/index.scss';
|
@import '@/static/scss/index.scss';
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<view>
|
<view>
|
||||||
<uni-row class="demo-uni-row" >
|
<uni-row class="demo-uni-row" >
|
||||||
<uni-col :span="8">
|
<uni-col :span="8">
|
||||||
<uni-data-select style="background: #fff" v-model="imei" :localdata="agriList" @change="changeAgri"></uni-data-select>
|
<uni-data-select v-model="imei" :localdata="agriList" @change="changeAgri"></uni-data-select>
|
||||||
|
|
||||||
</uni-col>
|
</uni-col>
|
||||||
<uni-col :span="16">
|
<uni-col :span="16">
|
||||||
|
|
@ -26,9 +26,7 @@
|
||||||
:ontouch="true"
|
:ontouch="true"
|
||||||
:disableScroll="true"
|
:disableScroll="true"
|
||||||
:onmovetip="true"
|
:onmovetip="true"
|
||||||
:onzoom="true"
|
|
||||||
tooltipFormat="tooltipDemo"
|
tooltipFormat="tooltipDemo"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<!-- 暂无数据 -->
|
<!-- 暂无数据 -->
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -128,53 +126,8 @@ export default {
|
||||||
getHistoryData(param).then(response => {
|
getHistoryData(param).then(response => {
|
||||||
if (response.code === 200 && response.data) {
|
if (response.code === 200 && response.data) {
|
||||||
var data = response.data;
|
var data = response.data;
|
||||||
var res = {
|
this.chartData = JSON.parse(JSON.stringify(data));
|
||||||
categories: data.timeList,
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: "温度1",
|
|
||||||
index: 0,
|
|
||||||
data: data.temp1List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "温度2",
|
|
||||||
index: 0,
|
|
||||||
data: data.temp2List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "温度3",
|
|
||||||
index: 0,
|
|
||||||
data: data.temp3List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "温度4",
|
|
||||||
index: 0,
|
|
||||||
data: data.temp4List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "湿度1",
|
|
||||||
index: 1,
|
|
||||||
data: data.humi1List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "湿度2",
|
|
||||||
index: 1,
|
|
||||||
data: data.humi2List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "湿度3",
|
|
||||||
index: 1,
|
|
||||||
data: data.humi3List
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "湿度4",
|
|
||||||
index: 1,
|
|
||||||
data: data.humi4List
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
this.chartData = JSON.parse(JSON.stringify(res));
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getAgriList() {
|
getAgriList() {
|
||||||
|
|
@ -208,7 +161,9 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
changeAgri(imei) {
|
changeAgri(imei) {
|
||||||
console.info("大棚下拉选择",imei)
|
if (imei) {
|
||||||
|
this.getServerData();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
changeDate(date) {
|
changeDate(date) {
|
||||||
// date[0]-date[1]
|
// date[0]-date[1]
|
||||||
|
|
@ -230,4 +185,7 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 500px;
|
height: 500px;
|
||||||
}
|
}
|
||||||
|
/deep/ .uni-stat__select {
|
||||||
|
background: #fff !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
## 2.0.7(2026-02-05)
|
||||||
|
- fix: 修复非web无法缩放问题
|
||||||
|
## 2.0.6(2025-12-13)
|
||||||
|
- feat: 修复类型问题
|
||||||
|
## 2.0.5(2025-12-12)
|
||||||
|
- fix: 修复uniappx 微信小程序模糊问题
|
||||||
|
## 2.0.4(2025-12-12)
|
||||||
|
- fix: 修复uniapp vue2 app引入依赖报错问题
|
||||||
|
## 2.0.3(2025-12-04)
|
||||||
|
- feat: autoHideTooltip默认为false
|
||||||
|
## 2.0.2(2025-11-24)
|
||||||
|
- feat: 增加`autoHideTooltip`属性
|
||||||
|
## 2.0.1(2025-10-28)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 2.0.0(2025-10-28)
|
||||||
|
- feat: 基于 Vue 3 Composition API 重构 uni-app 端组件,提升代码可维护性和性能
|
||||||
|
- feat: 升级内置 ECharts 至 v6 版本,支持最新图表特性和性能优化
|
||||||
|
## 1.0.4(2025-05-16)
|
||||||
|
- fix: 修复uniappx ios尺寸
|
||||||
|
## 1.0.3(2025-05-10)
|
||||||
|
- fix: 修复nvue缺少`isDisposed`
|
||||||
|
## 1.0.2(2025-03-21)
|
||||||
|
- fix: 修复词云无法设置字体大小的问题
|
||||||
|
## 1.0.1(2025-03-14)
|
||||||
|
- fix: 修复抖音小程序不显示问题
|
||||||
|
## 1.0.0(2025-02-27)
|
||||||
|
- fix: 修复uniappx微信小程序不显示问题
|
||||||
|
## 0.9.9(2025-02-24)
|
||||||
|
- feat: 更新v4
|
||||||
|
## 0.9.8(2024-12-20)
|
||||||
|
- fix: 修复 APP 无法放大问题
|
||||||
|
## 0.9.7(2024-12-02)
|
||||||
|
- feat: uniapp 增加`landscape`,当`landscape`为`true`时旋转90deg达到横屏效果。
|
||||||
|
- feat: 支持uniapp x 微信小程序
|
||||||
|
## 0.9.6(2024-07-23)
|
||||||
|
- fix: 修复 uni is not defined
|
||||||
|
## 0.9.5(2024-07-19)
|
||||||
|
- chore: 鸿蒙`measureText`为异步,异步字体不正常,使用模拟方式。
|
||||||
|
## 0.9.4(2024-07-18)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.9.3(2024-07-16)
|
||||||
|
- feat: 鸿蒙 canvas 事件缺失,待官方修复,如何在鸿蒙使用请看文档`常见问题 vue3`
|
||||||
|
## 0.9.2(2024-07-12)
|
||||||
|
- chore: 删除多余文件
|
||||||
|
## 0.9.1(2024-07-12)
|
||||||
|
- fix: 修复 安卓5不显示图表问题
|
||||||
|
## 0.9.0(2024-06-13)
|
||||||
|
- chore: 合并nvue和uvue
|
||||||
|
## 0.8.9(2024-05-19)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.8.8(2024-05-13)
|
||||||
|
- chore: 更新文档和uvue示例
|
||||||
|
## 0.8.7(2024-04-26)
|
||||||
|
- fix: uniapp x需要HBX 4.13以上
|
||||||
|
## 0.8.6(2024-04-10)
|
||||||
|
- feat: 支持 uniapp x ios
|
||||||
|
## 0.8.5(2024-04-03)
|
||||||
|
- fix: 修复 nvue `reset`传值不生效问题
|
||||||
|
- feat: 支持 uniapp x web
|
||||||
|
## 0.8.4(2024-01-27)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.8.3(2024-01-21)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.8.2(2024-01-21)
|
||||||
|
- feat: 支持 `uvue`
|
||||||
|
## 0.8.1(2023-08-24)
|
||||||
|
- fix: app 的`touch`事件为`object` 导致无法显示 `tooltip`
|
||||||
|
## 0.8.0(2023-08-22)
|
||||||
|
- fix: 离屏 报错问题
|
||||||
|
- fix: 微信小程序PC无法使用事件
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.7.9(2023-07-29)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.7.8(2023-07-29)
|
||||||
|
- fix: 离屏 报错问题
|
||||||
|
## 0.7.7(2023-07-27)
|
||||||
|
- chore: 更新文档
|
||||||
|
- chore: lime-echart 里的示例使用自定tooltips
|
||||||
|
- feat: 对支持离屏的使用离屏创建(微信、字节、支付宝)
|
||||||
|
## 0.7.6(2023-06-30)
|
||||||
|
- fix: vue3 报`width`的错
|
||||||
|
## 0.7.5(2023-05-25)
|
||||||
|
- chore: 更新文档 和 demo, 使用`lime-echart`这个标签即可查看示例
|
||||||
|
## 0.7.4(2023-05-22)
|
||||||
|
- chore: 增加关于钉钉小程序上传时提示安全问题的说明及修改建议
|
||||||
|
## 0.7.3(2023-05-16)
|
||||||
|
- chore: 更新 vue3 非微信小程序平台可能缺少`wx`的说明
|
||||||
|
## 0.7.2(2023-05-16)
|
||||||
|
- chore: 更新 vue3 非微信小程序平台的可以缺少`wx`的说明
|
||||||
|
## 0.7.1(2023-04-26)
|
||||||
|
- chore: 更新demo,使用`lime-echart`这个标签即可查看示例
|
||||||
|
- chore:微信小程序的`tooltip`文字有阴影,怀疑是微信的锅,临时解决方法是`tooltip.shadowBlur = 0`
|
||||||
|
## 0.7.0(2023-04-24)
|
||||||
|
- fix: 修复`setAttribute is not a function`
|
||||||
|
## 0.6.9(2023-04-15)
|
||||||
|
- chore: 更新文档,vue3请使用echarts esm的包
|
||||||
|
## 0.6.8(2023-03-22)
|
||||||
|
- feat: mac pc无法使用canvas 2d
|
||||||
|
## 0.6.7(2023-03-17)
|
||||||
|
- feat: 更新文档
|
||||||
|
## 0.6.6(2023-03-17)
|
||||||
|
- feat: 微信小程序PC已经支持canvas 2d,故去掉判断PC
|
||||||
|
## 0.6.5(2022-11-03)
|
||||||
|
- fix: 某些手机touches为对象,导致无法交互。
|
||||||
|
## 0.6.4(2022-10-28)
|
||||||
|
- fix: 优化点击事件的触发条件
|
||||||
|
## 0.6.3(2022-10-26)
|
||||||
|
- fix: 修复 dataZoom 拖动问题
|
||||||
|
## 0.6.2(2022-10-23)
|
||||||
|
- fix: 修复 飞书小程序 尺寸问题
|
||||||
|
## 0.6.1(2022-10-19)
|
||||||
|
- fix: 修复 PC mousewheel 事件 鼠标位置不准确的BUG,不兼容火狐!
|
||||||
|
- feat: showLoading 增加传参
|
||||||
|
## 0.6.0(2022-09-16)
|
||||||
|
- feat: 增加PC的mousewheel事件
|
||||||
|
## 0.5.4(2022-09-16)
|
||||||
|
- fix: 修复 nvue 动态数据不显示问题
|
||||||
|
## 0.5.3(2022-09-16)
|
||||||
|
- feat: 增加enableHover属性, 在PC端时当鼠标进入显示tooltip,不必按下。
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.5.2(2022-09-16)
|
||||||
|
- feat: 增加enableHover属性, 在PC端时当鼠标进入显示tooltip,不必按下。
|
||||||
|
## 0.5.1(2022-09-16)
|
||||||
|
- fix: 修复nvue报错
|
||||||
|
## 0.5.0(2022-09-15)
|
||||||
|
- feat: init(echarts, theme?:string, opts?:{}, callback: function(chart))
|
||||||
|
## 0.4.8(2022-09-11)
|
||||||
|
- feat: 增加 @finished
|
||||||
|
## 0.4.7(2022-08-24)
|
||||||
|
- chore: 去掉 stylus
|
||||||
|
## 0.4.6(2022-08-24)
|
||||||
|
- feat: 增加 beforeDelay
|
||||||
|
## 0.4.5(2022-08-12)
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.4.4(2022-08-12)
|
||||||
|
- fix: 修复 resize 无参数时报错
|
||||||
|
## 0.4.3(2022-08-07)
|
||||||
|
# 评论有说本插件对新手不友好,让我做不好就不要发出来。 还有的说跟官网一样,发出来做什么,给我整无语了。
|
||||||
|
# 所以在此提醒一下准备要下载的你,如果你从未使用过 echarts 请不要下载 或 谨慎下载。
|
||||||
|
# 如果你确认要下载,麻烦看完文档。还有请注意插件是让echarts在uniapp能运行,API 配置请自行去官网查阅!
|
||||||
|
# 如果你不会echarts 但又需要图表,市场上有个很优秀的图表插件 uchart 你可以去使用这款插件,uchart的作者人很好,也热情。
|
||||||
|
# 每个人都有自己的本职工作,如果你能力强可以自行兼容,如果使用了他人的插件也麻烦尊重他人的成果和劳动时间。谢谢。
|
||||||
|
# 为了心情愉悦,本人已经使用插件屏蔽差评。
|
||||||
|
- chore: 更新文档
|
||||||
|
## 0.4.2(2022-07-20)
|
||||||
|
- feat: 增加 resize
|
||||||
|
## 0.4.1(2022-06-07)
|
||||||
|
- fix: 修复 canvasToTempFilePath 不生效问题
|
||||||
|
## 0.4.0(2022-06-04)
|
||||||
|
- chore 为了词云 增加一个canvas 标签
|
||||||
|
- 词云下载地址[echart-wordcloud](https://ext.dcloud.net.cn/plugin?id=8430)
|
||||||
|
## 0.3.9(2022-06-02)
|
||||||
|
- chore: 更新文档
|
||||||
|
- tips: lines 不支持 `trailLength`
|
||||||
|
## 0.3.8(2022-05-31)
|
||||||
|
- fix: 修复 因mouse事件冲突tooltip跳动问题
|
||||||
|
## 0.3.7(2022-05-26)
|
||||||
|
- chore: 更新文档
|
||||||
|
- chore: 设置默认宽高300px
|
||||||
|
- fix: 修复 vue3 微信小程序 拖影BUG
|
||||||
|
- chore: 支持PC
|
||||||
|
## 0.3.5(2022-04-28)
|
||||||
|
- chore: 更新使用方式
|
||||||
|
- 🔔 必须使用hbuilderx 3.4.8-alpha以上
|
||||||
|
## 0.3.4(2021-08-03)
|
||||||
|
- chore: 增加 setOption的参数值
|
||||||
|
## 0.3.3(2021-07-22)
|
||||||
|
- fix: 修复 径向渐变报错的问题
|
||||||
|
## 0.3.2(2021-07-09)
|
||||||
|
- chore: 统一命名规范,无须主动引入组件
|
||||||
|
## [代码示例站点1](https://limeui.qcoon.cn/#/echart-example)
|
||||||
|
## [代码示例站点2](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.3.1(2021-06-21)
|
||||||
|
- fix: 修复 app-nvue ios is-enable 无效的问题
|
||||||
|
## [代码示例站点1](https://limeui.qcoon.cn/#/echart-example)
|
||||||
|
## [代码示例站点2](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.3.0(2021-06-14)
|
||||||
|
- fix: 修复 头条系小程序 2d 报 JSON.stringify 的问题
|
||||||
|
- 目前 头条系小程序 2d 无法在开发工具上预览,划动图表页面无法滚动,axisLabel 字体颜色无法更改,建议使用非2d。
|
||||||
|
## 0.2.9(2021-06-06)
|
||||||
|
- fix: 修复 头条系小程序 2d 放大的BUG
|
||||||
|
- 头条系小程序 2d 无法在开发工具上预览,也存在划动图表页面无法滚动的问题。
|
||||||
|
## [代码示例:http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.2.8(2021-05-19)
|
||||||
|
- fix: 修复 微信小程序 PC 显示过大的问题
|
||||||
|
## 0.2.7(2021-05-19)
|
||||||
|
- fix: 修复 微信小程序 PC 不显示问题
|
||||||
|
## [代码示例:http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.2.6(2021-05-14)
|
||||||
|
- feat: 支持 `image`
|
||||||
|
- feat: props 增加 `ec.clear`,更新时是否先删除图表样式
|
||||||
|
- feat: props 增加 `isDisableScroll` ,触摸图表时是否禁止页面滚动
|
||||||
|
- feat: props 增加 `webviewStyles` ,webview 的样式, 仅nvue有效
|
||||||
|
## 0.2.5(2021-05-13)
|
||||||
|
- docs: 插件用到了css 预编译器 [stylus](https://ext.dcloud.net.cn/plugin?name=compile-stylus) 请安装它
|
||||||
|
## 0.2.4(2021-05-12)
|
||||||
|
- fix: 修复 百度平台 多个图表ctx 和 渐变色 bug
|
||||||
|
- ## [代码示例:http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.2.3(2021-05-10)
|
||||||
|
- feat: 增加 `canvasToTempFilePath` 方法,用于生成图片
|
||||||
|
```js
|
||||||
|
this.$refs.chart.canvasToTempFilePath({success: (res) => {
|
||||||
|
console.log('tempFilePath:', res.tempFilePath)
|
||||||
|
}})
|
||||||
|
```
|
||||||
|
## 0.2.2(2021-05-10)
|
||||||
|
- feat: 增加 `dispose` 方法,用于销毁实例
|
||||||
|
- feat: 增加 `isClickable` 是否派发点击
|
||||||
|
- feat: 实验性的支持 `nvue` 使用要慎重考虑
|
||||||
|
- ## [代码示例:http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.2.1(2021-05-06)
|
||||||
|
- fix:修复 微信小程序 json 报错
|
||||||
|
- chore: `reset` 更改为 `setChart`
|
||||||
|
- feat: 增加 `isEnable` 开启初始化 启用这个后 无须再使用`init`方法
|
||||||
|
```html
|
||||||
|
<l-echart ref="chart" is-enable />
|
||||||
|
```
|
||||||
|
```js
|
||||||
|
// 显示加载
|
||||||
|
this.$refs.chart.showLoading()
|
||||||
|
// 使用实例回调
|
||||||
|
this.$refs.chart.setChart(chart => ...code)
|
||||||
|
// 直接设置图表配置
|
||||||
|
this.$refs.chart.setOption(data)
|
||||||
|
```
|
||||||
|
## 0.2.0(2021-05-05)
|
||||||
|
- fix:修复 头条 百度 偏移的问题
|
||||||
|
- docs: 更新文档
|
||||||
|
## [代码示例:http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)
|
||||||
|
## 0.1.0(2021-05-02)
|
||||||
|
- chore: 第一次上传,基本全端兼容,使用方法与官网一致。
|
||||||
|
- 已知BUG:非2d 无法使用背景色,已反馈官方
|
||||||
|
- 已知BUG:头条 百度 有许些偏移
|
||||||
|
- 后期计划:兼容nvue
|
||||||
|
|
@ -0,0 +1,399 @@
|
||||||
|
import {getDeviceInfo} from './utils';
|
||||||
|
|
||||||
|
const cacheChart = {}
|
||||||
|
const fontSizeReg = /([\d\.]+)px/;
|
||||||
|
class EventEmit {
|
||||||
|
constructor() {
|
||||||
|
this.__events = {};
|
||||||
|
}
|
||||||
|
on(type, listener) {
|
||||||
|
if (!type || !listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const events = this.__events[type] || [];
|
||||||
|
events.push(listener);
|
||||||
|
this.__events[type] = events;
|
||||||
|
}
|
||||||
|
emit(type, e) {
|
||||||
|
if (type.constructor === Object) {
|
||||||
|
e = type;
|
||||||
|
type = e && e.type;
|
||||||
|
}
|
||||||
|
if (!type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const events = this.__events[type];
|
||||||
|
if (!events || !events.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
events.forEach((listener) => {
|
||||||
|
listener.call(this, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
off(type, listener) {
|
||||||
|
const __events = this.__events;
|
||||||
|
const events = __events[type];
|
||||||
|
if (!events || !events.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!listener) {
|
||||||
|
delete __events[type];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0, len = events.length; i < len; i++) {
|
||||||
|
if (events[i] === listener) {
|
||||||
|
events.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Image {
|
||||||
|
constructor() {
|
||||||
|
this.currentSrc = null
|
||||||
|
this.naturalHeight = 0
|
||||||
|
this.naturalWidth = 0
|
||||||
|
this.width = 0
|
||||||
|
this.height = 0
|
||||||
|
this.tagName = 'IMG'
|
||||||
|
}
|
||||||
|
set src(src) {
|
||||||
|
this.currentSrc = src
|
||||||
|
uni.getImageInfo({
|
||||||
|
src,
|
||||||
|
success: (res) => {
|
||||||
|
this.naturalWidth = this.width = res.width
|
||||||
|
this.naturalHeight = this.height = res.height
|
||||||
|
this.onload()
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
this.onerror()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
get src() {
|
||||||
|
return this.currentSrc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class OffscreenCanvas {
|
||||||
|
constructor(ctx, com, canvasId) {
|
||||||
|
this.tagName = 'canvas'
|
||||||
|
this.com = com
|
||||||
|
this.canvasId = canvasId
|
||||||
|
this.ctx = ctx
|
||||||
|
}
|
||||||
|
set width(w) {
|
||||||
|
this.com.offscreenWidth = w
|
||||||
|
}
|
||||||
|
set height(h) {
|
||||||
|
this.com.offscreenHeight = h
|
||||||
|
}
|
||||||
|
get width() {
|
||||||
|
return this.com.offscreenWidth || 0
|
||||||
|
}
|
||||||
|
get height() {
|
||||||
|
return this.com.offscreenHeight || 0
|
||||||
|
}
|
||||||
|
getContext(type) {
|
||||||
|
return this.ctx
|
||||||
|
}
|
||||||
|
getImageData() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.com.$nextTick(() => {
|
||||||
|
uni.canvasGetImageData({
|
||||||
|
x:0,
|
||||||
|
y:0,
|
||||||
|
width: this.com.offscreenWidth,
|
||||||
|
height: this.com.offscreenHeight,
|
||||||
|
canvasId: this.canvasId,
|
||||||
|
success: (res) => {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(err)
|
||||||
|
},
|
||||||
|
}, this.com)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export class Canvas {
|
||||||
|
constructor(ctx, com, isNew, canvasNode={}) {
|
||||||
|
cacheChart[com.canvasId] = {ctx}
|
||||||
|
this.canvasId = com.canvasId;
|
||||||
|
this.chart = null;
|
||||||
|
this.isNew = isNew
|
||||||
|
this.tagName = 'canvas'
|
||||||
|
this.canvasNode = canvasNode;
|
||||||
|
this.com = com;
|
||||||
|
if (!isNew) {
|
||||||
|
this._initStyle(ctx)
|
||||||
|
}
|
||||||
|
this._initEvent();
|
||||||
|
this._ee = new EventEmit()
|
||||||
|
}
|
||||||
|
getContext(type) {
|
||||||
|
if (type === '2d') {
|
||||||
|
return this.ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setAttribute(key, value) {
|
||||||
|
if(key === 'aria-label') {
|
||||||
|
this.com['ariaLabel'] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setChart(chart) {
|
||||||
|
this.chart = chart;
|
||||||
|
}
|
||||||
|
createOffscreenCanvas(param){
|
||||||
|
if(!this.children) {
|
||||||
|
// this.com.isOffscreenCanvas = true
|
||||||
|
// this.com.offscreenWidth = param.width||300
|
||||||
|
// this.com.offscreenHeight = param.height||300
|
||||||
|
// const com = this.com
|
||||||
|
// const canvasId = this.com.offscreenCanvasId
|
||||||
|
// const context = uni.createCanvasContext(canvasId, this.com)
|
||||||
|
// this._initStyle(context)
|
||||||
|
// this.children = new OffscreenCanvas(context, com, canvasId)
|
||||||
|
}
|
||||||
|
return this.children
|
||||||
|
}
|
||||||
|
appendChild(child) {
|
||||||
|
console.log('child', child)
|
||||||
|
}
|
||||||
|
dispatchEvent(type, e) {
|
||||||
|
if(typeof type == 'object') {
|
||||||
|
this._ee.emit(type.type, type);
|
||||||
|
} else {
|
||||||
|
this._ee.emit(type, e);
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
attachEvent() {
|
||||||
|
}
|
||||||
|
detachEvent() {
|
||||||
|
}
|
||||||
|
addEventListener(type, listener) {
|
||||||
|
this._ee.on(type, listener)
|
||||||
|
}
|
||||||
|
removeEventListener(type, listener) {
|
||||||
|
this._ee.off(type, listener)
|
||||||
|
}
|
||||||
|
_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, font);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
_initStyle(ctx, child) {
|
||||||
|
const styles = [
|
||||||
|
'fillStyle',
|
||||||
|
'strokeStyle',
|
||||||
|
'fontSize',
|
||||||
|
'globalAlpha',
|
||||||
|
'opacity',
|
||||||
|
'textAlign',
|
||||||
|
'textBaseline',
|
||||||
|
'shadow',
|
||||||
|
'lineWidth',
|
||||||
|
'lineCap',
|
||||||
|
'lineJoin',
|
||||||
|
'lineDash',
|
||||||
|
'miterLimit',
|
||||||
|
// #ifdef H5 || APP
|
||||||
|
'font',
|
||||||
|
// #endif
|
||||||
|
];
|
||||||
|
const colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\b/g;
|
||||||
|
styles.forEach(style => {
|
||||||
|
Object.defineProperty(ctx, style, {
|
||||||
|
set: value => {
|
||||||
|
// #ifdef H5 || APP
|
||||||
|
if (style === 'font' && fontSizeReg.test(value)) {
|
||||||
|
const match = fontSizeReg.exec(value);
|
||||||
|
ctx.setFontSize(match[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
if (style === 'opacity') {
|
||||||
|
ctx.setGlobalAlpha(value)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (style !== 'fillStyle' && style !== 'strokeStyle' || value !== 'none' && value !== null) {
|
||||||
|
// #ifdef H5 || APP-PLUS || MP-BAIDU
|
||||||
|
if(typeof value == 'object') {
|
||||||
|
if (value.hasOwnProperty('colorStop') || value.hasOwnProperty('colors')) {
|
||||||
|
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
if(colorReg.test(value)) {
|
||||||
|
value = value.replace(colorReg, '#$1$1$2$2$3$3')
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if(!this.isNew && !child) {
|
||||||
|
ctx.uniDrawImage = ctx.drawImage
|
||||||
|
ctx.drawImage = (...a) => {
|
||||||
|
a[0] = a[0].src
|
||||||
|
ctx.uniDrawImage(...a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!ctx.createRadialGradient) {
|
||||||
|
ctx.createRadialGradient = function() {
|
||||||
|
return ctx.createCircularGradient(...[...arguments].slice(-3))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 字节不支持
|
||||||
|
if (!ctx.strokeText) {
|
||||||
|
ctx.strokeText = (...a) => {
|
||||||
|
ctx.fillText(...a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 钉钉不支持 , 鸿蒙是异步
|
||||||
|
if (!ctx.measureText || getDeviceInfo().osName == 'harmonyos') {
|
||||||
|
ctx._measureText = ctx.measureText
|
||||||
|
const strLen = (str) => {
|
||||||
|
let len = 0;
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) {
|
||||||
|
len++;
|
||||||
|
} else {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
ctx.measureText = (text, font) => {
|
||||||
|
let fontSize = ctx?.state?.fontSize || 12;
|
||||||
|
if (font) {
|
||||||
|
fontSize = parseInt(font.match(/([\d\.]+)px/)[1])
|
||||||
|
}
|
||||||
|
fontSize /= 2;
|
||||||
|
let isBold = fontSize >= 16;
|
||||||
|
const widthFactor = isBold ? 1.3 : 1;
|
||||||
|
// ctx._measureText(text, (res) => {})
|
||||||
|
return {
|
||||||
|
width: strLen(text) * fontSize * widthFactor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_initEvent(e) {
|
||||||
|
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
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
set width(w) {
|
||||||
|
this.canvasNode.width = w
|
||||||
|
}
|
||||||
|
set height(h) {
|
||||||
|
this.canvasNode.height = h
|
||||||
|
}
|
||||||
|
|
||||||
|
get width() {
|
||||||
|
return this.canvasNode.width || 0
|
||||||
|
}
|
||||||
|
get height() {
|
||||||
|
return this.canvasNode.height || 0
|
||||||
|
}
|
||||||
|
get ctx() {
|
||||||
|
return cacheChart[this.canvasId]['ctx'] || null
|
||||||
|
}
|
||||||
|
set chart(chart) {
|
||||||
|
cacheChart[this.canvasId]['chart'] = chart
|
||||||
|
}
|
||||||
|
get chart() {
|
||||||
|
return cacheChart[this.canvasId]['chart'] || null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dispatch(name, {x,y, wheelDelta}) {
|
||||||
|
this.dispatch(name, {
|
||||||
|
zrX: x,
|
||||||
|
zrY: y,
|
||||||
|
zrDelta: wheelDelta,
|
||||||
|
preventDefault: () => {},
|
||||||
|
stopPropagation: () =>{}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function setCanvasCreator(echarts, {canvas, node}) {
|
||||||
|
if(echarts && !echarts.registerPreprocessor) {
|
||||||
|
return console.warn('echarts 版本不对或未传入echarts,vue3请使用esm格式')
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function loadImage(src, onload, onerror) {
|
||||||
|
let img = null
|
||||||
|
if(node && node.createImage) {
|
||||||
|
img = node.createImage()
|
||||||
|
img.onload = onload.bind(img);
|
||||||
|
img.onerror = onerror.bind(img);
|
||||||
|
img.src = src;
|
||||||
|
return img
|
||||||
|
} else {
|
||||||
|
img = new Image()
|
||||||
|
img.onload = onload.bind(img)
|
||||||
|
img.onerror = onerror.bind(img);
|
||||||
|
img.src = src
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(echarts.setPlatformAPI) {
|
||||||
|
echarts.setPlatformAPI({
|
||||||
|
loadImage: canvas.setChart ? loadImage : null,
|
||||||
|
createCanvas(){
|
||||||
|
const key = 'createOffscreenCanvas'
|
||||||
|
return uni.canIUse(key) && uni[key] ? uni[key]({type: '2d'}) : canvas
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if(echarts.setCanvasCreator) {
|
||||||
|
echarts.setCanvasCreator(() => {
|
||||||
|
return canvas;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,322 @@
|
||||||
|
<template>
|
||||||
|
<!-- #ifdef APP -->
|
||||||
|
<web-view class="lime-echart" ref="chartRef" @load="loaded" :style="[lStyle]" :webview-styles="[webviewStyles]"
|
||||||
|
src="/uni_modules/lime-echart/static/app/uvue.html?v=10112">
|
||||||
|
</web-view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef WEB -->
|
||||||
|
<div class="lime-echart" ref="chartRef"></div>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef WEB || APP-->
|
||||||
|
<view class="lime-echart">
|
||||||
|
<canvas style="width:100%; height:100%" v-if="canvasid" :id="canvasid" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="uts" setup>
|
||||||
|
// @ts-nocheck
|
||||||
|
import { echartsProps } from './type';
|
||||||
|
import { Echarts } from './uvue';
|
||||||
|
// #ifdef WEB
|
||||||
|
import { dispatch } from './canvas';
|
||||||
|
import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP || WEB
|
||||||
|
import { Canvas, setCanvasCreator, dispatch } from './canvas';
|
||||||
|
import { wrapTouch, convertTouchesToArray, devicePixelRatio, sleep, canIUseCanvas2d, getRect } from './utils';
|
||||||
|
// #endif
|
||||||
|
type EChartsResolveCallback = (value : Echarts) => void
|
||||||
|
|
||||||
|
const emits = defineEmits(['finished'])
|
||||||
|
const props = withDefaults(defineProps<echartsProps>(), {
|
||||||
|
isDisableScroll: false,
|
||||||
|
isClickable: true,
|
||||||
|
autoHideTooltip: false,
|
||||||
|
enableHover: false,
|
||||||
|
landscape: false,
|
||||||
|
beforeDelay: 30,
|
||||||
|
})
|
||||||
|
const instance = getCurrentInstance()!;
|
||||||
|
const canvasid = `lime-echart-${instance.uid}`
|
||||||
|
const finished = ref(false)
|
||||||
|
const initializationQueue = [] as EChartsResolveCallback[]
|
||||||
|
const callbackQueue = [] as EChartsResolveCallback[]
|
||||||
|
// let context = null as UniWebViewElement | null
|
||||||
|
let chartInstance = null as Echarts | null
|
||||||
|
let chartRef = ref<UniWebViewElement | null>(null)
|
||||||
|
let canvasNode:any|null = null
|
||||||
|
const processInitializationQueue = () => {
|
||||||
|
// #ifdef APP
|
||||||
|
if (finished.value) {
|
||||||
|
if (chartInstance == null) {
|
||||||
|
chartInstance = new Echarts(chartRef.value!)
|
||||||
|
}
|
||||||
|
while (initializationQueue.length > 0) {
|
||||||
|
const resolve = initializationQueue.pop() as EChartsResolveCallback
|
||||||
|
resolve(chartInstance!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP
|
||||||
|
while (initializationQueue.length > 0) {
|
||||||
|
if (chartInstance != null) {
|
||||||
|
const resolve = initializationQueue.pop() as EChartsResolveCallback
|
||||||
|
resolve(chartInstance!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
if (chartInstance != null) {
|
||||||
|
while (callbackQueue.length > 0) {
|
||||||
|
const callback = callbackQueue.pop() as EChartsResolveCallback
|
||||||
|
callback(chartInstance!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifdef APP
|
||||||
|
const loaded = (event : UniWebViewLoadEvent) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
event.preventDefault()
|
||||||
|
nextTick(()=> {
|
||||||
|
chartRef.value?.getBoundingClientRectAsync()?.then(res => {
|
||||||
|
if(res.width > 0 && res.height > 0) {
|
||||||
|
finished.value = true
|
||||||
|
processInitializationQueue()
|
||||||
|
emits('finished')
|
||||||
|
} else {
|
||||||
|
console.warn('【lime-echart】获取尺寸失败,请检查代码样式')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
|
const checkInitialization = () : boolean => {
|
||||||
|
if (chartInstance == null) {
|
||||||
|
console.warn(`组件还未初始化,请先使用 init`)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const setOption = (option : UTSJSONObject) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.setOption(option);
|
||||||
|
}
|
||||||
|
const showLoading = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.showLoading();
|
||||||
|
}
|
||||||
|
const hideLoading = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.hideLoading();
|
||||||
|
}
|
||||||
|
const clear = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.clear();
|
||||||
|
}
|
||||||
|
const dispose = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.dispose();
|
||||||
|
}
|
||||||
|
const resize = (size : UTSJSONObject) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.resize(size);
|
||||||
|
}
|
||||||
|
const canvasToTempFilePath = (opt : UTSJSONObject) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
// #ifdef APP
|
||||||
|
chartInstance!.canvasToTempFilePath(opt);
|
||||||
|
// #endif
|
||||||
|
// #ifdef WEB
|
||||||
|
opt.success?.({
|
||||||
|
// @ts-ignore
|
||||||
|
tempFilePath: chartInstance!._api.getDataURL()
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
// #ifndef WEB || APP
|
||||||
|
if(canvasNode) {
|
||||||
|
opt.success?.({
|
||||||
|
tempFilePath: canvasNode.toDataURL()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.canvasToTempFilePath({
|
||||||
|
...opt,
|
||||||
|
canvasId
|
||||||
|
}, instance.proxy);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifdef APP
|
||||||
|
function init(callback : ((chartInstance : Echarts) => void) | null) : Promise<Echarts> {
|
||||||
|
if (callback != null) {
|
||||||
|
callbackQueue.push(callback)
|
||||||
|
}
|
||||||
|
return new Promise<Echarts>((resolve) => {
|
||||||
|
initializationQueue.push(resolve)
|
||||||
|
processInitializationQueue()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP
|
||||||
|
// #ifndef WEB
|
||||||
|
let use2dCanvas = canIUseCanvas2d()
|
||||||
|
const getContext = async () => {
|
||||||
|
return new Promise((resolve, reject)=>{
|
||||||
|
uni.createCanvasContextAsync({
|
||||||
|
id: canvasid,
|
||||||
|
component: instance.proxy!,
|
||||||
|
success: (context : CanvasContext) => {
|
||||||
|
canvasNode = context
|
||||||
|
const canvasContext = context.getContext('2d')!;
|
||||||
|
const canvas = canvasContext.canvas;
|
||||||
|
let uniCanvas;
|
||||||
|
const width = canvas.offsetWidth
|
||||||
|
const height = canvas.offsetHeight
|
||||||
|
// 处理高清屏逻辑
|
||||||
|
const dpr = devicePixelRatio//uni.getDeviceInfo().devicePixelRatio ?? 1;
|
||||||
|
canvas.width = canvas.offsetWidth * dpr;
|
||||||
|
canvas.height = canvas.offsetHeight * dpr;
|
||||||
|
canvasContext.scale(dpr, dpr); // 仅需调用一次,当调用 reset 方法后需要再次 scale
|
||||||
|
if(use2dCanvas) {
|
||||||
|
uniCanvas = new Canvas(canvasContext, instance.proxy, true, context);
|
||||||
|
} else {
|
||||||
|
uniCanvas = new Canvas(canvasContext, instance.proxy, false);
|
||||||
|
}
|
||||||
|
resolve({ canvas: uniCanvas, width, height, devicePixelRatio: dpr, node: context});
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
reject(err)
|
||||||
|
console.log('err', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
const getTouch = (e) => {
|
||||||
|
const touches = e.touches[0]
|
||||||
|
// #ifdef WEB
|
||||||
|
// @ts-ignore
|
||||||
|
const rect = chart!.getZr().dom.getBoundingClientRect();
|
||||||
|
const touch = {
|
||||||
|
x: touches.clientX - rect.left,
|
||||||
|
y: touches.clientY - rect.top
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef WEB
|
||||||
|
const touch = {
|
||||||
|
x: touches.x,
|
||||||
|
y: touches.y
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return touch
|
||||||
|
}
|
||||||
|
const handleTouchStart = (e) => {
|
||||||
|
if (chartInstance == null) return
|
||||||
|
const handler = chartInstance.getZr().handler;
|
||||||
|
const touch = getTouch(e)
|
||||||
|
dispatch.call(handler, 'mousedown', touch)
|
||||||
|
dispatch.call(handler, 'mousemove', touch)
|
||||||
|
handler.processGesture(wrapTouch(e), 'start');
|
||||||
|
}
|
||||||
|
const handleTouchMove = (e) => {
|
||||||
|
if (chartInstance == null) return
|
||||||
|
const handler = chartInstance.getZr().handler;
|
||||||
|
const touch = getTouch(e)
|
||||||
|
dispatch.call(handler, 'mousemove', touch)
|
||||||
|
handler.processGesture(wrapTouch(e), 'change');
|
||||||
|
}
|
||||||
|
const handleTouchEnd = (e) => {
|
||||||
|
if (chartInstance == null) return
|
||||||
|
const handler = chartInstance.getZr().handler;
|
||||||
|
const touch = e.changedTouches ? e.changedTouches[0] : {}
|
||||||
|
handler.processGesture(wrapTouch(e), 'end');
|
||||||
|
dispatch.call(handler, 'mouseup', touch)
|
||||||
|
dispatch.call(handler, 'click', touch)
|
||||||
|
}
|
||||||
|
async function init(echarts : any, ...args : any[]) : Promise<Echarts> {
|
||||||
|
const library = echarts || echartsLibrary
|
||||||
|
if (library == null) {
|
||||||
|
console.error('请确保已经引入了 ECharts 库');
|
||||||
|
return Promise.reject('请确保已经引入了 ECharts 库');
|
||||||
|
}
|
||||||
|
let theme : string | null = null
|
||||||
|
let opts = {}
|
||||||
|
let callback : Function | null = null;
|
||||||
|
|
||||||
|
args.forEach(item => {
|
||||||
|
if (typeof item === 'function') {
|
||||||
|
callback = item
|
||||||
|
} else if (['string'].includes(typeof item)) {
|
||||||
|
theme = item
|
||||||
|
} else if (typeof item === 'object') {
|
||||||
|
opts = item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// #ifdef WEB
|
||||||
|
library.env.domSupported = true
|
||||||
|
library.env.hasGlobalWindow = true
|
||||||
|
library.env.node = false
|
||||||
|
library.env.pointerEventsSupported = false
|
||||||
|
library.env.svgSupported = true
|
||||||
|
library.env.touchEventsSupported = true
|
||||||
|
library.env.transform3dSupported = true
|
||||||
|
library.env.transformSupported = true
|
||||||
|
library.env.worker = false
|
||||||
|
library.env.wxa = false
|
||||||
|
chartInstance = library.init(chartRef.value, theme, opts)
|
||||||
|
// window.addEventListener('touchstart', touchstart)
|
||||||
|
// window.addEventListener('touchmove', touchmove)
|
||||||
|
// window.addEventListener('touchend', touchend)
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef WEB
|
||||||
|
let config = await getContext();
|
||||||
|
setCanvasCreator(library, config)
|
||||||
|
chartInstance = library.init(config.canvas, theme, Object.assign({}, config, opts))
|
||||||
|
// #endif
|
||||||
|
if (callback != null && typeof callback == 'function') {
|
||||||
|
callbackQueue.push(callback)
|
||||||
|
}
|
||||||
|
return new Promise<Echarts>((resolve) => {
|
||||||
|
initializationQueue.push(resolve)
|
||||||
|
processInitializationQueue()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
finished.value = true
|
||||||
|
processInitializationQueue()
|
||||||
|
emits('finished')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
// #ifdef WEB
|
||||||
|
// window.removeEventListener('touchstart', touchstart)
|
||||||
|
// window.removeEventListener('touchmove', touchmove)
|
||||||
|
// window.removeEventListener('touchend', touchend)
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
init,
|
||||||
|
setOption,
|
||||||
|
showLoading,
|
||||||
|
hideLoading,
|
||||||
|
clear,
|
||||||
|
dispose,
|
||||||
|
resize,
|
||||||
|
canvasToTempFilePath
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.lime-echart {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,484 @@
|
||||||
|
<template>
|
||||||
|
<!-- #ifndef APP-NVUE || WEB -->
|
||||||
|
<view class="lime-echart"
|
||||||
|
:style="[lStyle]"
|
||||||
|
v-if="canvasId"
|
||||||
|
ref="chartContainer"
|
||||||
|
:aria-label="'图表'">
|
||||||
|
<canvas class="lime-echart__canvas"
|
||||||
|
type="2d"
|
||||||
|
:style="[styles]"
|
||||||
|
:id="canvasId"
|
||||||
|
:disable-scroll="isDisableScroll"
|
||||||
|
:canvas-id="canvasId"
|
||||||
|
@touchstart="handleTouchStart"
|
||||||
|
@touchmove="handleTouchMove"
|
||||||
|
@touchend="handleTouchEnd">
|
||||||
|
</canvas>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef WEB -->
|
||||||
|
<div class="lime-echart" ref="chartContainer" :style="[styles, lStyle]"></div>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<view class="lime-echart" :style="[lStyle]">
|
||||||
|
<web-view class="lime-echart__canvas"
|
||||||
|
:webview-styles="webviewStyles"
|
||||||
|
:style="[styles]"
|
||||||
|
ref="chartContainer"
|
||||||
|
src="/uni_modules/lime-echart/static/app/uvue.html?v=1"
|
||||||
|
@pagefinish="isInitialized = true"
|
||||||
|
@onPostMessage="handleWebviewMessage"></web-view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
// @ts-nocheck
|
||||||
|
import { defineComponent, getCurrentInstance, ref, onMounted, nextTick, onBeforeUnmount, watch, computed } from './vue'
|
||||||
|
import echartProps from './props'
|
||||||
|
|
||||||
|
// #ifndef APP-NVUE || WEB
|
||||||
|
import { Canvas, setCanvasCreator, dispatch } from './canvas';
|
||||||
|
import { wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect, getDeviceInfo } from './utils';
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
import { base64ToPath, sleep } from './utils';
|
||||||
|
import { Echarts } from './nvue'
|
||||||
|
// #endif
|
||||||
|
// #ifdef WEB
|
||||||
|
import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-VUE
|
||||||
|
// #ifdef VUE3
|
||||||
|
import '@/uni_modules/lime-echart/static/app/echarts.min.js';
|
||||||
|
const echartsLibrary = globalThis.echarts
|
||||||
|
// #endif
|
||||||
|
// #ifdef VUE2
|
||||||
|
import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
||||||
|
// #endif
|
||||||
|
// #endif
|
||||||
|
export default defineComponent({
|
||||||
|
props: echartProps,
|
||||||
|
emits: ['finished'],
|
||||||
|
setup(props, { emit, expose }) {
|
||||||
|
// #ifndef APP-NVUE || WEB || APP-VUE
|
||||||
|
let echartsLibrary = null
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
const instance = getCurrentInstance()!;
|
||||||
|
const canvasId = `lime-echart-${instance.uid}`
|
||||||
|
const isInitialized = ref(false)
|
||||||
|
const chartContainer = ref(null)
|
||||||
|
|
||||||
|
type ChartOptions = Record<string, any>
|
||||||
|
type EChartsInstance = typeof echartsLibrary
|
||||||
|
type EChartsResolveCallback = (value: EChartsInstance) => void
|
||||||
|
|
||||||
|
const initializationQueue = [] as EChartsResolveCallback[]
|
||||||
|
const callbackQueue = [] as EChartsResolveCallback[]
|
||||||
|
|
||||||
|
let chartInstance: null | EChartsInstance = null
|
||||||
|
|
||||||
|
const styles = computed(()=> {
|
||||||
|
if(props.landscape) {
|
||||||
|
return {
|
||||||
|
transform: 'translate(-50%,-50%) rotate(90deg)',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const checkInitialization = (): boolean => {
|
||||||
|
if(chartInstance) return false
|
||||||
|
console.warn(`组件还未初始化,请先使用 init`)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const setOption = (options: ChartOptions) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.setOption(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hideLoading = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.showLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
const showLoading = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.hideLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const dispose = () => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartInstance!.dispose();
|
||||||
|
}
|
||||||
|
const processInitializationQueue = () => {
|
||||||
|
while (initializationQueue.length > 0) {
|
||||||
|
if (chartInstance != null) {
|
||||||
|
const resolve = initializationQueue.pop() as EChartsResolveCallback
|
||||||
|
resolve(chartInstance!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chartInstance != null) {
|
||||||
|
while (callbackQueue.length > 0) {
|
||||||
|
const callback = callbackQueue.pop() as EChartsResolveCallback
|
||||||
|
callback(chartInstance!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resize = (dimensions?: { width?: number; height?: number }) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
// #ifdef APP-NVUE || WEB
|
||||||
|
chartInstance!.resize(dimensions);
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-NVUE || WEB
|
||||||
|
getRect(`#${canvasId}`, instance.proxy).then(res => {
|
||||||
|
chartInstance!.resize({width: res.width, height: res.height});
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
let chartFile = ref(null);
|
||||||
|
const handleWebviewMessage = (e) => {
|
||||||
|
const detail = e?.detail?.data[0] || null;
|
||||||
|
const data = detail?.data
|
||||||
|
const key = detail?.event
|
||||||
|
const options = data?.options
|
||||||
|
const event = data?.event
|
||||||
|
const file = detail?.file
|
||||||
|
if (key == 'log' && data) {
|
||||||
|
console.log(data)
|
||||||
|
}
|
||||||
|
if(event) {
|
||||||
|
chartInstance.dispatchAction(event.replace(/"/g,''), options)
|
||||||
|
}
|
||||||
|
if(file) {
|
||||||
|
chartFile.value = file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvasToTempFilePath = (options: ChartOptions) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
chartContainer.value.evalJs(`canvasToTempFilePath()`);
|
||||||
|
watch(chartFile, async (file) =>{
|
||||||
|
if(!file) return
|
||||||
|
const tempFilePath = await base64ToPath(file)
|
||||||
|
options.success({tempFilePath})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getContext = () => {
|
||||||
|
if(isInitialized.value) {
|
||||||
|
return Promise.resolve(isInitialized.value)
|
||||||
|
}
|
||||||
|
return new Promise(resolve => {
|
||||||
|
watch(isInitialized, (val) =>{
|
||||||
|
if(!val) return
|
||||||
|
resolve(val)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const init = async (echarts, ...args) => {
|
||||||
|
let theme: string | null = null
|
||||||
|
let config:Record<string, any> = {}
|
||||||
|
let callback: Function | null = null;
|
||||||
|
|
||||||
|
args.forEach(item => {
|
||||||
|
if (typeof item === 'function') {
|
||||||
|
callback = item
|
||||||
|
} else if (typeof item === 'string') {
|
||||||
|
theme = item
|
||||||
|
} else if (typeof item === 'object') {
|
||||||
|
config = item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(props.beforeDelay) {
|
||||||
|
await sleep(props.beforeDelay)
|
||||||
|
}
|
||||||
|
await getContext();
|
||||||
|
chartInstance = new Echarts(chartContainer.value)
|
||||||
|
chartContainer.value.evalJs(`init(null, null, ${JSON.stringify(config)}, ${theme})`)
|
||||||
|
if (callback && typeof callback === 'function') {
|
||||||
|
callbackQueue.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise<EChartsInstance>((resolve) => {
|
||||||
|
nextTick(()=>{
|
||||||
|
initializationQueue.push(resolve)
|
||||||
|
processInitializationQueue()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
|
// #ifndef APP-NVUE || WEB
|
||||||
|
let canvasNode;
|
||||||
|
const canvasToTempFilePath = (options: ChartOptions) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
if(canvasNode) {
|
||||||
|
options.success?.({
|
||||||
|
tempFilePath: canvasNode.toDataURL()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.canvasToTempFilePath({
|
||||||
|
...options,
|
||||||
|
canvasId
|
||||||
|
}, instance.proxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getContext = () => {
|
||||||
|
return getRect(`#${canvasId}`, instance.proxy).then(res => {
|
||||||
|
let dpr = devicePixelRatio
|
||||||
|
let {width, height, node} = res
|
||||||
|
let canvas: Canvas | null = null;
|
||||||
|
if(!(width || height)) {
|
||||||
|
return Promise.reject('no rect')
|
||||||
|
}
|
||||||
|
if(node && node.getContext) {
|
||||||
|
const ctx = node.getContext('2d');
|
||||||
|
canvas = new Canvas(ctx, instance.proxy, true, node);
|
||||||
|
canvasNode = node
|
||||||
|
} else {
|
||||||
|
dpr = 1
|
||||||
|
const ctx = uni.createCanvasContext(canvasId, instance.proxy);
|
||||||
|
canvas = new Canvas(ctx, instance.proxy, false);
|
||||||
|
}
|
||||||
|
return { canvas, width, height, devicePixelRatio: dpr, node }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const getTouch = (e) => {
|
||||||
|
const touches = e.touches[0]
|
||||||
|
const touch = props.landscape
|
||||||
|
? {
|
||||||
|
x: touches.y,
|
||||||
|
y: touches.x
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
x: touches.x,
|
||||||
|
y: touches.y
|
||||||
|
}
|
||||||
|
return touch
|
||||||
|
}
|
||||||
|
const handleTouchStart = (e) => {
|
||||||
|
if (chartInstance == null) return
|
||||||
|
const handler = chartInstance.getZr().handler;
|
||||||
|
const touch = getTouch(e)
|
||||||
|
dispatch.call(handler, 'mousedown', touch)
|
||||||
|
dispatch.call(handler, 'mousemove', touch)
|
||||||
|
handler.processGesture(wrapTouch(e), 'start');
|
||||||
|
}
|
||||||
|
const handleTouchMove = (e) => {
|
||||||
|
if (chartInstance == null) return
|
||||||
|
const handler = chartInstance.getZr().handler;
|
||||||
|
const touch = getTouch(e)
|
||||||
|
dispatch.call(handler, 'mousemove', touch)
|
||||||
|
handler.processGesture(wrapTouch(e), 'change');
|
||||||
|
}
|
||||||
|
const handleTouchEnd = (e) => {
|
||||||
|
if (chartInstance == null) return
|
||||||
|
const handler = chartInstance.getZr().handler;
|
||||||
|
const touch = e.changedTouches ? e.changedTouches[0] : {}
|
||||||
|
handler.processGesture(wrapTouch(e), 'end');
|
||||||
|
dispatch.call(handler, 'mouseup', touch)
|
||||||
|
dispatch.call(handler, 'click', touch)
|
||||||
|
}
|
||||||
|
const init = async (echartsLib: EChartsInstance = echartsLibrary, ...args: any[]): Promise<EChartsInstance> => {
|
||||||
|
const library = echartsLib || echartsLibrary
|
||||||
|
if (!library) {
|
||||||
|
console.error('ECharts library is required');
|
||||||
|
return Promise.reject('ECharts library is required');
|
||||||
|
}
|
||||||
|
let theme: string | null = null
|
||||||
|
let config:Record<string, any> = {}
|
||||||
|
let callback: Function | null = null;
|
||||||
|
|
||||||
|
args.forEach(item => {
|
||||||
|
if (typeof item === 'function') {
|
||||||
|
callback = item
|
||||||
|
} else if (typeof item === 'string') {
|
||||||
|
theme = item
|
||||||
|
} else if (typeof item === 'object') {
|
||||||
|
config = item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(props.beforeDelay) {
|
||||||
|
await sleep(props.beforeDelay)
|
||||||
|
}
|
||||||
|
let options = await getContext();
|
||||||
|
setCanvasCreator(library, options)
|
||||||
|
chartInstance = library.init(options.canvas, theme, Object.assign({}, options, config))
|
||||||
|
if (callback && typeof callback === 'function') {
|
||||||
|
callbackQueue.push(callback)
|
||||||
|
}
|
||||||
|
return new Promise<EChartsInstance>((resolve) => {
|
||||||
|
initializationQueue.push(resolve)
|
||||||
|
processInitializationQueue()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
|
// #ifdef WEB
|
||||||
|
const canvasToTempFilePath = (options: ChartOptions) => {
|
||||||
|
if (checkInitialization()) return
|
||||||
|
options.success?.({
|
||||||
|
tempFilePath: chartInstance._api.getDataURL()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = async (echarts: EChartsInstance = echartsLibrary, ...args: any[]): Promise<EChartsInstance> => {
|
||||||
|
const library = echarts || echartsLibrary
|
||||||
|
if (!library) {
|
||||||
|
console.error('ECharts library is required');
|
||||||
|
return Promise.reject('ECharts library is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
let theme: string | null = null
|
||||||
|
let config = {}
|
||||||
|
let callback: Function | null = null;
|
||||||
|
|
||||||
|
args.forEach(item => {
|
||||||
|
if (typeof item === 'function') {
|
||||||
|
callback = item
|
||||||
|
} else if (typeof item === 'string') {
|
||||||
|
theme = item
|
||||||
|
} else if (typeof item === 'object') {
|
||||||
|
config = item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Configure ECharts environment
|
||||||
|
library.env.domSupported = true
|
||||||
|
library.env.hasGlobalWindow = true
|
||||||
|
library.env.node = false
|
||||||
|
library.env.pointerEventsSupported = false
|
||||||
|
library.env.svgSupported = true
|
||||||
|
library.env.touchEventsSupported = true
|
||||||
|
library.env.transform3dSupported = true
|
||||||
|
library.env.transformSupported = true
|
||||||
|
library.env.worker = false
|
||||||
|
library.env.wxa = false
|
||||||
|
|
||||||
|
chartInstance = library.init(chartContainer.value, theme, config)
|
||||||
|
|
||||||
|
if (callback != null && typeof callback === 'function') {
|
||||||
|
callbackQueue.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise<EChartsInstance>((resolve) => {
|
||||||
|
initializationQueue.push(resolve)
|
||||||
|
processInitializationQueue()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
isInitialized.value = true
|
||||||
|
// #endif
|
||||||
|
emit('finished')
|
||||||
|
processInitializationQueue()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
onBeforeUnmount(()=> {
|
||||||
|
clear()
|
||||||
|
dispose()
|
||||||
|
})
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
expose({
|
||||||
|
init,
|
||||||
|
setOption,
|
||||||
|
hideLoading,
|
||||||
|
showLoading,
|
||||||
|
clear,
|
||||||
|
dispose,
|
||||||
|
resize,
|
||||||
|
canvasToTempFilePath
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
return {
|
||||||
|
canvasId,
|
||||||
|
chartContainer,
|
||||||
|
styles,
|
||||||
|
// #ifndef WEB || APP-NVUE
|
||||||
|
handleTouchStart,
|
||||||
|
handleTouchMove,
|
||||||
|
handleTouchEnd,
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
handleWebviewMessage,
|
||||||
|
isInitialized,
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE2
|
||||||
|
init,
|
||||||
|
setOption,
|
||||||
|
hideLoading,
|
||||||
|
showLoading,
|
||||||
|
clear,
|
||||||
|
dispose,
|
||||||
|
resize,
|
||||||
|
canvasToTempFilePath,
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.lime-echart {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
flex: 1;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.lime-echart__canvas {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
flex: 1;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.lime-echart__mask {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
export class Echarts {
|
||||||
|
eventMap = new Map()
|
||||||
|
constructor(webview) {
|
||||||
|
this.webview = webview
|
||||||
|
this.options = null
|
||||||
|
}
|
||||||
|
setOption() {
|
||||||
|
this.options = arguments
|
||||||
|
console.log('setOption1')
|
||||||
|
this.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);
|
||||||
|
}
|
||||||
|
getOption() {
|
||||||
|
return this.options
|
||||||
|
}
|
||||||
|
showLoading() {
|
||||||
|
this.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);
|
||||||
|
}
|
||||||
|
hideLoading() {
|
||||||
|
this.webview.evalJs(`hideLoading()`);
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
this.webview.evalJs(`clear()`);
|
||||||
|
}
|
||||||
|
dispose() {
|
||||||
|
this.webview.evalJs(`dispose()`);
|
||||||
|
}
|
||||||
|
resize(size) {
|
||||||
|
if(size) {
|
||||||
|
this.webview.evalJs(`resize(${JSON.stringify(size)})`);
|
||||||
|
} else {
|
||||||
|
this.webview.evalJs(`resize()`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on(type, ...args) {
|
||||||
|
const query = args[0]
|
||||||
|
const useQuery = query && typeof query != 'function'
|
||||||
|
const param = useQuery ? [type, query] : [type]
|
||||||
|
const key = `${type}${useQuery ? JSON.stringify(query): '' }`
|
||||||
|
const callback = useQuery ? args[1]: args[0]
|
||||||
|
if(typeof callback == 'function'){
|
||||||
|
this.eventMap.set(key, callback)
|
||||||
|
}
|
||||||
|
this.webview.evalJs(`on(${JSON.stringify(param)})`);
|
||||||
|
console.warn('nvue 暂不支持事件')
|
||||||
|
}
|
||||||
|
dispatchAction(type, options){
|
||||||
|
const handler = this.eventMap.get(type)
|
||||||
|
if(handler){
|
||||||
|
handler(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 不让报错 无实际作用
|
||||||
|
isDisposed() {
|
||||||
|
return !!this.webview
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
export default {
|
||||||
|
// #ifdef MP-WEIXIN || MP-TOUTIAO
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: '2d'
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
webviewStyles: Object,
|
||||||
|
// #endif
|
||||||
|
lStyle: String,
|
||||||
|
isDisableScroll: Boolean,
|
||||||
|
isClickable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
enableHover: Boolean,
|
||||||
|
beforeDelay: {
|
||||||
|
type: Number,
|
||||||
|
default: 30
|
||||||
|
},
|
||||||
|
landscape: Boolean,
|
||||||
|
autoHideTooltip: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
export interface echartsProps {
|
||||||
|
webviewStyles?: UTSJSONObject,
|
||||||
|
lStyle?: string | UTSJSONObject
|
||||||
|
isDisableScroll: boolean;
|
||||||
|
isClickable: boolean;
|
||||||
|
enableHover: boolean;
|
||||||
|
beforeDelay: number;
|
||||||
|
landscape: boolean;
|
||||||
|
autoHideTooltip: boolean;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,181 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
/**
|
||||||
|
* 获取设备基础信息
|
||||||
|
*
|
||||||
|
* @see [uni.getDeviceInfo](https://uniapp.dcloud.net.cn/api/system/getDeviceInfo.html)
|
||||||
|
*/
|
||||||
|
export function getDeviceInfo() {
|
||||||
|
if (uni.getDeviceInfo || uni.canIUse('getDeviceInfo')) {
|
||||||
|
return uni.getDeviceInfo();
|
||||||
|
} else {
|
||||||
|
return uni.getSystemInfoSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取窗口信息
|
||||||
|
*
|
||||||
|
* @see [uni.getWindowInfo](https://uniapp.dcloud.net.cn/api/system/getWindowInfo.html)
|
||||||
|
*/
|
||||||
|
export function getWindowInfo() {
|
||||||
|
if (uni.getWindowInfo || uni.canIUse('getWindowInfo')) {
|
||||||
|
return uni.getWindowInfo();
|
||||||
|
} else {
|
||||||
|
return uni.getSystemInfoSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取APP基础信息
|
||||||
|
*
|
||||||
|
* @see [uni.getAppBaseInfo](https://uniapp.dcloud.net.cn/api/system/getAppBaseInfo.html)
|
||||||
|
*/
|
||||||
|
export function getAppBaseInfo() {
|
||||||
|
if (uni.getAppBaseInfo || uni.canIUse('getAppBaseInfo')) {
|
||||||
|
return uni.getAppBaseInfo();
|
||||||
|
} else {
|
||||||
|
return uni.getSystemInfoSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
// 计算版本
|
||||||
|
export function 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], 10)
|
||||||
|
const num2 = parseInt(v2[i], 10)
|
||||||
|
|
||||||
|
if (num1 > num2) {
|
||||||
|
return 1
|
||||||
|
} else if (num1 < num2) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
// const systemInfo = uni.getSystemInfoSync();
|
||||||
|
|
||||||
|
function gte(version) {
|
||||||
|
// 截止 2023-03-22 mac pc小程序不支持 canvas 2d
|
||||||
|
// let {
|
||||||
|
// SDKVersion,
|
||||||
|
// platform
|
||||||
|
// } = systemInfo;
|
||||||
|
const { platform } = getDeviceInfo();
|
||||||
|
let { SDKVersion } = getAppBaseInfo();
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
SDKVersion = my.SDKVersion
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
return platform !== 'mac' && compareVersion(SDKVersion, version) >= 0;
|
||||||
|
// #endif
|
||||||
|
return compareVersion(SDKVersion, version) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function canIUseCanvas2d() {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
return gte('2.9.0');
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
return gte('2.7.0');
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
return gte('1.78.0');
|
||||||
|
// #endif
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export function convertTouchesToArray(touches) {
|
||||||
|
// 如果 touches 是一个数组,则直接返回它
|
||||||
|
if (Array.isArray(touches)) {
|
||||||
|
return touches;
|
||||||
|
}
|
||||||
|
// 如果touches是一个对象,则转换为数组
|
||||||
|
if (typeof touches === 'object' && touches !== null) {
|
||||||
|
return Object.values(touches);
|
||||||
|
}
|
||||||
|
// 对于其他类型,直接返回它
|
||||||
|
return touches;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wrapTouch(event) {
|
||||||
|
event.touches = convertTouchesToArray(event.touches)
|
||||||
|
for (let i = 0; i < event.touches.length; ++i) {
|
||||||
|
const touch = event.touches[i];
|
||||||
|
touch.offsetX = touch.x;
|
||||||
|
touch.offsetY = touch.y;
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
// export const devicePixelRatio = uni.getSystemInfoSync().pixelRatio
|
||||||
|
export const devicePixelRatio = getWindowInfo().pixelRatio;
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
export function base64ToPath(base64) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
|
||||||
|
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
|
||||||
|
bitmap.loadBase64Data(base64, () => {
|
||||||
|
if (!format) {
|
||||||
|
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
||||||
|
}
|
||||||
|
const time = new Date().getTime();
|
||||||
|
const filePath = `_doc/uniapp_temp/${time}.${format}`
|
||||||
|
|
||||||
|
bitmap.save(filePath, {},
|
||||||
|
() => {
|
||||||
|
bitmap.clear()
|
||||||
|
resolve(filePath)
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
bitmap.clear()
|
||||||
|
console.error(`${JSON.stringify(error)}`)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
}, (error) => {
|
||||||
|
bitmap.clear()
|
||||||
|
console.error(`${JSON.stringify(error)}`)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
|
||||||
|
export function sleep(time) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(true)
|
||||||
|
}, time)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getRect(selector, context) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const dom = uni.createSelectorQuery().in(context).select(selector);
|
||||||
|
const result = (rect) => {
|
||||||
|
if (rect) {
|
||||||
|
resolve(rect)
|
||||||
|
} else {
|
||||||
|
reject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dom.fields({
|
||||||
|
node: true,
|
||||||
|
size: true,
|
||||||
|
rect: true
|
||||||
|
}, result).exec()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
// #ifdef APP
|
||||||
|
type EchartsEventHandler = (event: UTSJSONObject)=>void
|
||||||
|
// type EchartsTempResolve = (obj : UTSJSONObject) => void
|
||||||
|
// type EchartsTempOptions = UTSJSONObject
|
||||||
|
export class Echarts {
|
||||||
|
options: UTSJSONObject = {} as UTSJSONObject
|
||||||
|
context: UniWebViewElement
|
||||||
|
eventMap: Map<string, EchartsEventHandler> = new Map()
|
||||||
|
private temp: UTSJSONObject[] = []
|
||||||
|
constructor(context: UniWebViewElement){
|
||||||
|
this.context = context
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
init(){
|
||||||
|
this.context.evalJS(`init(null, null, ${JSON.stringify({})})`)
|
||||||
|
|
||||||
|
this.context.addEventListener('message', (e : UniWebViewMessageEvent) => {
|
||||||
|
// event.stopPropagation()
|
||||||
|
// event.preventDefault()
|
||||||
|
|
||||||
|
const detail = e.detail.data[0]
|
||||||
|
const file = detail.getString('file')
|
||||||
|
const data = detail.get('data')
|
||||||
|
const key = detail.getString('event')
|
||||||
|
const options = typeof data == 'object' ? (data as UTSJSONObject).getJSON('options'): null
|
||||||
|
const event = typeof data == 'object' ? (data as UTSJSONObject).getString('event'): null
|
||||||
|
if (key == 'log' && data != null) {
|
||||||
|
console.log(data)
|
||||||
|
}
|
||||||
|
if (event != null && options != null) {
|
||||||
|
this.dispatchAction(event.replace(/"/g,''), options)
|
||||||
|
}
|
||||||
|
if(file != null){
|
||||||
|
while (this.temp.length > 0) {
|
||||||
|
const opt = this.temp.pop()
|
||||||
|
const success = opt?.get('success')
|
||||||
|
if(typeof success == 'function'){
|
||||||
|
success as (res: UTSJSONObject) => void
|
||||||
|
success({tempFilePath: file})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setOption(option: UTSJSONObject){
|
||||||
|
this.options = option;
|
||||||
|
this.context.evalJS(`setOption(${JSON.stringify([option])})`)
|
||||||
|
}
|
||||||
|
setOption(option: UTSJSONObject, notMerge: boolean = false, lazyUpdate: boolean = false){
|
||||||
|
this.options = option;
|
||||||
|
this.context.evalJS(`setOption(${JSON.stringify([option, notMerge, lazyUpdate])})`)
|
||||||
|
}
|
||||||
|
setOption(option: UTSJSONObject, notMerge: UTSJSONObject){
|
||||||
|
this.options = option;
|
||||||
|
this.context.evalJS(`setOption(${JSON.stringify([option, notMerge])})`)
|
||||||
|
}
|
||||||
|
getOption(): UTSJSONObject {
|
||||||
|
return this.options
|
||||||
|
}
|
||||||
|
showLoading(){
|
||||||
|
this.context.evalJS(`showLoading(${JSON.stringify([] as any[])})`);
|
||||||
|
}
|
||||||
|
showLoading(type: string, opts: UTSJSONObject){
|
||||||
|
this.context.evalJS(`showLoading(${JSON.stringify([type, opts])})`);
|
||||||
|
}
|
||||||
|
hideLoading(){
|
||||||
|
this.context.evalJS(`hideLoading()`);
|
||||||
|
}
|
||||||
|
clear(){
|
||||||
|
this.context.evalJS(`clear()`);
|
||||||
|
}
|
||||||
|
dispose(){
|
||||||
|
this.context.evalJS(`dispose()`);
|
||||||
|
}
|
||||||
|
resize(size:UTSJSONObject){
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.context.evalJS(`resize(${JSON.stringify(size)})`);
|
||||||
|
},0)
|
||||||
|
}
|
||||||
|
resize(){
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.context.evalJS(`resize()`);
|
||||||
|
},10)
|
||||||
|
|
||||||
|
}
|
||||||
|
on(type:string, query: any, callback: EchartsEventHandler) {
|
||||||
|
const key = `${type}${JSON.stringify(query)}`
|
||||||
|
if(typeof callback == 'function'){
|
||||||
|
this.eventMap.set(key, callback)
|
||||||
|
}
|
||||||
|
this.context.evalJS(`on(${JSON.stringify([type, query])})`);
|
||||||
|
console.warn('uvue 暂不支持事件')
|
||||||
|
}
|
||||||
|
on(type:string, callback: EchartsEventHandler) {
|
||||||
|
const key = `${type}`
|
||||||
|
if(typeof callback == 'function'){
|
||||||
|
this.eventMap.set(key, callback)
|
||||||
|
}
|
||||||
|
this.context.evalJS(`on(${JSON.stringify([type])})`);
|
||||||
|
console.warn('uvue 暂不支持事件')
|
||||||
|
}
|
||||||
|
dispatchAction(type:string, options: UTSJSONObject){
|
||||||
|
const handler = this.eventMap.get(type)
|
||||||
|
if(handler!=null){
|
||||||
|
handler(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canvasToTempFilePath(opt: UTSJSONObject){
|
||||||
|
// this.context.evalJS(`on(${JSON.stringify(opt)})`);
|
||||||
|
this.context.evalJS(`canvasToTempFilePath(${JSON.stringify(opt)})`);
|
||||||
|
this.temp.push(opt)
|
||||||
|
}
|
||||||
|
isDisposed():boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP
|
||||||
|
export class Echarts {
|
||||||
|
constructor() {}
|
||||||
|
setOption(option: UTSJSONObject): void
|
||||||
|
isDisposed(): boolean;
|
||||||
|
clear(): void;
|
||||||
|
resize(size:UTSJSONObject): void;
|
||||||
|
resize(): void;
|
||||||
|
canvasToTempFilePath(opt : UTSJSONObject): void;
|
||||||
|
dispose(): void;
|
||||||
|
showLoading(cfg?: UTSJSONObject): void;
|
||||||
|
showLoading(name?: string, cfg?: UTSJSONObject): void;
|
||||||
|
hideLoading(): void;
|
||||||
|
getZr(): any
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
export * from 'vue';
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef VUE3
|
||||||
|
export * from '@vue/composition-api';
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
import Vue from 'vue'
|
||||||
|
import VueCompositionAPI from '@vue/composition-api'
|
||||||
|
Vue.use(VueCompositionAPI)
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
|
@ -0,0 +1,227 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view style="height: 750rpx; position: relative">
|
||||||
|
<l-echart ref="chart" @finished="init"></l-echart>
|
||||||
|
<view
|
||||||
|
class="customTooltips"
|
||||||
|
:style="{ left: position[0] + 'px', top: position[1] + 'px' }"
|
||||||
|
v-if="params.length && position.length && showTip"
|
||||||
|
>
|
||||||
|
<view>这是个自定的tooltips</view>
|
||||||
|
<view>{{ params[0]['axisValue'] }}</view>
|
||||||
|
<view v-for="item in params">
|
||||||
|
<view>
|
||||||
|
<text>{{ item.seriesName }}</text>
|
||||||
|
<text>{{ item.value }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// nvue 不需要引入
|
||||||
|
// #ifdef VUE2
|
||||||
|
import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
|
||||||
|
// #endif
|
||||||
|
// #ifdef VUE3
|
||||||
|
// #ifdef MP
|
||||||
|
// 由于vue3 使用vite 不支持umd格式的包,小程序依然可以使用,但需要使用require
|
||||||
|
const echarts = require('../../static/echarts.min')
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
// 由于 vue3 使用vite 不支持umd格式的包,故引入npm的包
|
||||||
|
import * as echarts from 'echarts/dist/echarts.esm'
|
||||||
|
// #endif
|
||||||
|
// #endif
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showTip: false,
|
||||||
|
position: [],
|
||||||
|
params: [],
|
||||||
|
option: {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
// shadowBlur: 0,
|
||||||
|
textStyle: {
|
||||||
|
textShadowBlur: 0,
|
||||||
|
},
|
||||||
|
renderMode: 'richText',
|
||||||
|
position: (point, params, dom, rect, size) => {
|
||||||
|
// 假设自定义的tooltips尺寸
|
||||||
|
const box = [170, 170]
|
||||||
|
// 偏移
|
||||||
|
const offsetX = point[0] < size.viewSize[0] / 2 ? 20 : -box[0] - 20
|
||||||
|
const offsetY = point[1] < size.viewSize[1] / 2 ? 20 : -box[1] - 20
|
||||||
|
const x = point[0] + offsetX
|
||||||
|
const y = point[1] + offsetY
|
||||||
|
|
||||||
|
this.position = [x, y]
|
||||||
|
this.params = params
|
||||||
|
},
|
||||||
|
formatter: (params, ticket, callback) => {},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '邮件营销',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [120, 132, 101, 134, 90, 230, 210],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联盟广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '视频广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [150, 232, 201, 154, 190, 330, 410],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直接访问',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [320, 332, 301, 334, 390, 330, 320],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '搜索引擎',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
// init(echarts, theme?:string, opts?:{}, chart => {})
|
||||||
|
// echarts 必填, 非nvue必填,nvue不用填
|
||||||
|
// theme 可选,应用的主题,目前只支持名称,如:'dark'
|
||||||
|
// opts = { // 可选
|
||||||
|
// locale?: string // 从 `5.0.0` 开始支持
|
||||||
|
// }
|
||||||
|
// chart => {} , callback 返回图表实例
|
||||||
|
// setTimeout(()=>{
|
||||||
|
// this.$refs.chart.init(echarts, chart => {
|
||||||
|
// chart.setOption(this.option);
|
||||||
|
// });
|
||||||
|
// },300)
|
||||||
|
this.$refs.chart.init(echarts, (chart) => {
|
||||||
|
chart.setOption(this.option)
|
||||||
|
|
||||||
|
// 监听tooltip显示事件
|
||||||
|
chart.on('showTip', (params) => {
|
||||||
|
this.showTip = true
|
||||||
|
console.log('showTip::')
|
||||||
|
})
|
||||||
|
chart.on('hideTip', (params) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showTip = false
|
||||||
|
}, 300)
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
// shadowBlur: 0,
|
||||||
|
textStyle: {
|
||||||
|
textShadowBlur: 0,
|
||||||
|
},
|
||||||
|
renderMode: 'richText',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '邮件营销',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [1120, 132, 101, 134, 90, 230, 210],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联盟广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '视频广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [150, 632, 201, 154, 190, 330, 410],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直接访问',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 332, 301, 334, 390, 330, 320],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '搜索引擎',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
chart.setOption(option)
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
this.$refs.chart.canvasToTempFilePath({
|
||||||
|
success(res) {
|
||||||
|
console.log('res::::', res)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.customTooltips {
|
||||||
|
position: absolute;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
<template>
|
||||||
|
<view style="width: 100%; height: 408px;">
|
||||||
|
<l-echart ref="chartRef" @finished="init"></l-echart>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showTip: false,
|
||||||
|
option: {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
// shadowBlur: 0,
|
||||||
|
textStyle: {
|
||||||
|
textShadowBlur: 0
|
||||||
|
},
|
||||||
|
renderMode: 'richText',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '邮件营销',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [120, 132, 101, 134, 90, 230, 210]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联盟广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '视频广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [150, 232, 201, 154, 190, 330, 410]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直接访问',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [320, 332, 301, 334, 390, 330, 320]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '搜索引擎',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
console.log('lime echarts nvue')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
const chartRef = this.$refs['chartRef']
|
||||||
|
chartRef.init(chart => {
|
||||||
|
chart.setOption(this.option);
|
||||||
|
|
||||||
|
|
||||||
|
setTimeout(()=>{
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
// shadowBlur: 0,
|
||||||
|
textStyle: {
|
||||||
|
textShadowBlur: 0
|
||||||
|
},
|
||||||
|
renderMode: 'richText',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '邮件营销',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [120, 132, 101, 134, 90, 230, 210]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联盟广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '视频广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [150, 232, 201, 154, 190, 330, 410]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直接访问',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [320, 332, 301, 334, 390, 330, 320]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '搜索引擎',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
chart.setOption(option);
|
||||||
|
},1000)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
// this.$refs.chart.canvasToTempFilePath({
|
||||||
|
// success(res) {
|
||||||
|
// console.log('res::::', res)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
<template>
|
||||||
|
<view style="width: 100%; height: 408px;">
|
||||||
|
<l-echart ref="chartRef" @finished="init"></l-echart>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="uts" setup>
|
||||||
|
// #ifdef MP
|
||||||
|
// 引入小程序依赖包,require只能是当前文件的相对路径
|
||||||
|
const echarts = require('../../../../static/echarts.min.js')
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
// 非小程序不需要引入
|
||||||
|
const echarts = null
|
||||||
|
// #endif
|
||||||
|
const chartRef = ref<LEchartComponentPublicInstance|null>(null)
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
// shadowBlur: 0,
|
||||||
|
textStyle: {
|
||||||
|
textShadowBlur: 0
|
||||||
|
},
|
||||||
|
renderMode: 'richText',
|
||||||
|
},
|
||||||
|
// formatter: async (params: any) => {
|
||||||
|
// console.log('params', params)
|
||||||
|
// return 1
|
||||||
|
// },
|
||||||
|
legend: {
|
||||||
|
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
|
||||||
|
},
|
||||||
|
// grid: {
|
||||||
|
// left: '3%',
|
||||||
|
// right: '4%',
|
||||||
|
// bottom: '3%',
|
||||||
|
// containLabel: true
|
||||||
|
// },
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '邮件营销',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [120, 132, 101, 134, 90, 230, 210]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联盟广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '视频广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [150, 232, 201, 154, 190, 330, 410]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直接访问',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [320, 332, 301, 334, 390, 330, 320]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '搜索引擎',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = async () =>{
|
||||||
|
if(chartRef.value== null) return
|
||||||
|
const chart = await chartRef.value!.init(echarts)
|
||||||
|
chart.setOption(option)
|
||||||
|
// chart.on('mouseover', function (params) {
|
||||||
|
// console.log('params', params);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
// setTimeout(()=> {
|
||||||
|
// const option1 = {
|
||||||
|
// tooltip: {
|
||||||
|
// trigger: 'axis',
|
||||||
|
// // shadowBlur: 0,
|
||||||
|
// textStyle: {
|
||||||
|
// textShadowBlur: 0
|
||||||
|
// },
|
||||||
|
// renderMode: 'richText',
|
||||||
|
// },
|
||||||
|
// legend: {
|
||||||
|
// data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
|
||||||
|
// },
|
||||||
|
// grid: {
|
||||||
|
// left: '3%',
|
||||||
|
// right: '4%',
|
||||||
|
// bottom: '3%',
|
||||||
|
// containLabel: true
|
||||||
|
// },
|
||||||
|
// xAxis: {
|
||||||
|
// type: 'category',
|
||||||
|
// boundaryGap: false,
|
||||||
|
// data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||||
|
// },
|
||||||
|
// yAxis: {
|
||||||
|
// type: 'value'
|
||||||
|
// },
|
||||||
|
// series: [
|
||||||
|
// {
|
||||||
|
// name: '邮件营销',
|
||||||
|
// type: 'line',
|
||||||
|
// stack: '总量',
|
||||||
|
// data: [820, 132, 101, 134, 90, 230, 210]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '联盟广告',
|
||||||
|
// type: 'line',
|
||||||
|
// stack: '总量',
|
||||||
|
// data: [220, 182, 191, 234, 290, 330, 310]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '视频广告',
|
||||||
|
// type: 'line',
|
||||||
|
// stack: '总量',
|
||||||
|
// data: [950, 232, 201, 154, 190, 330, 410]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '直接访问',
|
||||||
|
// type: 'line',
|
||||||
|
// stack: '总量',
|
||||||
|
// data: [320, 332, 301, 334, 390, 330, 320]
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '搜索引擎',
|
||||||
|
// type: 'line',
|
||||||
|
// stack: '总量',
|
||||||
|
// data: [820, 932, 901, 934, 1290, 1330, 1320]
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// chart.setOption(option1)
|
||||||
|
// },1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view style="height: 750rpx; position: relative">
|
||||||
|
<l-echart ref="chart" @finished="init"></l-echart>
|
||||||
|
<view class="customTooltips" :style="{ left: position[0] + 'px', top: position[1] + 'px' }"
|
||||||
|
v-if="params.length && position.length && showTip">
|
||||||
|
<view>这是个自定的tooltips</view>
|
||||||
|
<view>{{ params[0]['axisValue'] }}</view>
|
||||||
|
<view v-for="item in params">
|
||||||
|
<view>
|
||||||
|
<text>{{ item.seriesName }}</text>
|
||||||
|
<text>{{ item.value }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef MP
|
||||||
|
// 引入小程序依赖包,require只能是当前文件的相对路径
|
||||||
|
const echarts = require('../../../../static/echarts.min.js');
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
// 非小程序不需要引入
|
||||||
|
const echarts = null
|
||||||
|
// #endif
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showTip: false,
|
||||||
|
position: [],
|
||||||
|
params: [],
|
||||||
|
option: {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
// shadowBlur: 0,
|
||||||
|
textStyle: {
|
||||||
|
textShadowBlur: 0,
|
||||||
|
},
|
||||||
|
renderMode: 'richText',
|
||||||
|
position: (point, params, dom, rect, size) => {
|
||||||
|
// 假设自定义的tooltips尺寸
|
||||||
|
const box = [170, 170]
|
||||||
|
// 偏移
|
||||||
|
const offsetX = point[0] < size.viewSize[0] / 2 ? 20 : -box[0] - 20
|
||||||
|
const offsetY = point[1] < size.viewSize[1] / 2 ? 20 : -box[1] - 20
|
||||||
|
const x = point[0] + offsetX
|
||||||
|
const y = point[1] + offsetY
|
||||||
|
|
||||||
|
this.position = [x, y]
|
||||||
|
this.params = params
|
||||||
|
},
|
||||||
|
formatter: (params, ticket, callback) => {},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'],
|
||||||
|
},
|
||||||
|
// grid: {
|
||||||
|
// left: '3%',
|
||||||
|
// right: '4%',
|
||||||
|
// bottom: '3%',
|
||||||
|
// containLabel: true,
|
||||||
|
// },
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: '邮件营销',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [120, 132, 101, 134, 90, 230, 210],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '联盟广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '视频广告',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [150, 232, 201, 154, 190, 330, 410],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '直接访问',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [320, 332, 301, 334, 390, 330, 320],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '搜索引擎',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async init() {
|
||||||
|
// init(echarts, theme?:string, opts?:{}, chart => {})
|
||||||
|
// echarts 必填, 非nvue必填,nvue不用填
|
||||||
|
// theme 可选,应用的主题,目前只支持名称,如:'dark'
|
||||||
|
// opts = { // 可选
|
||||||
|
// locale?: string // 从 `5.0.0` 开始支持
|
||||||
|
// }
|
||||||
|
// chart => {} , callback 返回图表实例
|
||||||
|
// setTimeout(()=>{
|
||||||
|
// this.$refs.chart.init(echarts, chart => {
|
||||||
|
// chart.setOption(this.option);
|
||||||
|
// });
|
||||||
|
// },300)
|
||||||
|
const chart = await this.$refs.chart.init(echarts)
|
||||||
|
chart.setOption(this.option)
|
||||||
|
// 监听tooltip显示事件
|
||||||
|
chart.on('showTip', (params) => {
|
||||||
|
this.showTip = true
|
||||||
|
console.log('showTip::')
|
||||||
|
})
|
||||||
|
chart.on('hideTip', (params) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showTip = false
|
||||||
|
}, 300)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
this.$refs.chart.canvasToTempFilePath({
|
||||||
|
success(res) {
|
||||||
|
console.log('res::::', res)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.customTooltips {
|
||||||
|
position: absolute;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
{
|
||||||
|
"id": "lime-echart",
|
||||||
|
"displayName": "lime-echart echarts图表",
|
||||||
|
"version": "2.0.7",
|
||||||
|
"description": "lime-echart 为 UniApp 和 UniAppX 提供 ECharts 图表兼容支持, 使 ECharts 图表能在H5、小程序、App中运行",
|
||||||
|
"keywords": [
|
||||||
|
"echarts",
|
||||||
|
"canvas",
|
||||||
|
"图表",
|
||||||
|
"可视化"
|
||||||
|
],
|
||||||
|
"repository": "https://gitee.com/liangei/lime-echart",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.6.4",
|
||||||
|
"uni-app": "^4.65",
|
||||||
|
"uni-app-x": "^4.71"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "",
|
||||||
|
"type": "component-vue",
|
||||||
|
"darkmode": "x",
|
||||||
|
"i18n": "x",
|
||||||
|
"widescreen": "x"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "x",
|
||||||
|
"aliyun": "x",
|
||||||
|
"alipay": "x"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"uni-app": {
|
||||||
|
"vue": {
|
||||||
|
"vue2": "√",
|
||||||
|
"vue3": "√"
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"safari": "√",
|
||||||
|
"chrome": "√"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"vue": "√",
|
||||||
|
"nvue": "√",
|
||||||
|
"android": {
|
||||||
|
"extVersion": "",
|
||||||
|
"minVersion": "21"
|
||||||
|
},
|
||||||
|
"ios": "√",
|
||||||
|
"harmony": "√"
|
||||||
|
},
|
||||||
|
"mp": {
|
||||||
|
"weixin": "√",
|
||||||
|
"alipay": "√",
|
||||||
|
"toutiao": "√",
|
||||||
|
"baidu": "√",
|
||||||
|
"kuaishou": "√",
|
||||||
|
"jd": "√",
|
||||||
|
"harmony": "-",
|
||||||
|
"qq": "√",
|
||||||
|
"lark": "√",
|
||||||
|
"xhs": "-"
|
||||||
|
},
|
||||||
|
"quickapp": {
|
||||||
|
"huawei": "-",
|
||||||
|
"union": "-"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uni-app-x": {
|
||||||
|
"web": {
|
||||||
|
"safari": "√",
|
||||||
|
"chrome": "√"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"android": {
|
||||||
|
"extVersion": "",
|
||||||
|
"minVersion": "21"
|
||||||
|
},
|
||||||
|
"ios": "√",
|
||||||
|
"harmony": "√"
|
||||||
|
},
|
||||||
|
"mp": {
|
||||||
|
"weixin": "√"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"echarts": "^5.4.1",
|
||||||
|
"zrender": "^5.4.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,499 @@
|
||||||
|
# lime-echart 📊
|
||||||
|
|
||||||
|
为 UniApp 和 UniAppX 提供 ECharts 图表兼容支持,使 ECharts 图表能在 H5、小程序、App 等多端环境中正常运行。
|
||||||
|
|
||||||
|
## 特性 ✨
|
||||||
|
|
||||||
|
- 📱 **跨平台兼容**:支持 H5、微信小程序、支付宝小程序、App 等多端
|
||||||
|
- 🎯 **简单易用**:统一 API,使用方式与原生 ECharts 基本一致
|
||||||
|
- ⚡ **性能优化**:针对不同平台进行了渲染优化
|
||||||
|
- 🔄 **双框架支持**:同时支持 uni-app 和 uni-app-x
|
||||||
|
|
||||||
|
## 文档与示例 📚
|
||||||
|
|
||||||
|
更多详细文档与示例:
|
||||||
|
- [lime-echart 组件文档](https://limeui.qcoon.cn/#/echart)
|
||||||
|
- [在线示例](https://limeui.qcoon.cn/#/echart-example)
|
||||||
|
- [ECharts 官方示例](https://echarts.apache.org/examples/zh/index.html)
|
||||||
|
- [lime-echart 组件文档2](https://limex.qcoon.cn/components/echart.html) (将来用到,目前未上线)
|
||||||
|
|
||||||
|
## 安装方法 📦
|
||||||
|
|
||||||
|
### 插件市场安装
|
||||||
|
|
||||||
|
1. 在uni-app插件市场中搜索并导入`lime-echart`
|
||||||
|
2. 导入后重新编译项目
|
||||||
|
3. 在页面中直接使用 `l-echart` 组件
|
||||||
|
|
||||||
|
### CLI 项目安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 下载插件到项目的 src/uni_modules 目录
|
||||||
|
mkdir -p src/uni_modules
|
||||||
|
# 将插件解压到上述目录
|
||||||
|
```
|
||||||
|
|
||||||
|
## 前置依赖 ⚙️
|
||||||
|
|
||||||
|
### 小程序平台(重点说明)
|
||||||
|
|
||||||
|
小程序平台必须下载并引入 ECharts 自定义构建包:
|
||||||
|
|
||||||
|
1. 小程序中引入ECharts方式:
|
||||||
|
- **本地构建文件**
|
||||||
|
- 访问 [ECharts 在线构建](https://echarts.apache.org/zh/builder.html) 下载所需图表类型的精简版
|
||||||
|
- 注意:在线构建工具**仅支持生成UMD格式**(默认,`echarts.min.js`),通过 `require` 引入
|
||||||
|
- 建议只勾选项目所需的图表类型和组件,以减小文件体积
|
||||||
|
|
||||||
|
2. **文件放置位置**:
|
||||||
|
- 📁 **主包**:将文件放入项目根目录的 `static` 文件夹
|
||||||
|
- 📁 **分包**:将文件放入对应分包的 `static` 文件夹(如 `pagesB/static/`)
|
||||||
|
|
||||||
|
3. **相对路径引用示例**:
|
||||||
|
```js
|
||||||
|
// UMD格式 - 页面位于主包根目录 - 相对路径引用示例(仅在线构建或本地文件使用)
|
||||||
|
// ├─pages
|
||||||
|
// │ └─index
|
||||||
|
// │ └─index.vue
|
||||||
|
// └─static
|
||||||
|
const echarts = require('../../static/echarts.min.js')
|
||||||
|
|
||||||
|
// UMD格式 - 页面位于主包三层目录 - 相对路径引用示例(仅在线构建或本地文件使用)
|
||||||
|
// ├─pages
|
||||||
|
// │ └─user
|
||||||
|
// │ └─settings
|
||||||
|
// │ └─profile.vue
|
||||||
|
// └─static
|
||||||
|
const echarts = require('../../../static/echarts.min.js')
|
||||||
|
|
||||||
|
// UMD格式 - 页面位于分包中 - 相对路径引用示例(仅在线构建或本地文件使用)
|
||||||
|
// ├─pagesB (分包)
|
||||||
|
// │ ├─static
|
||||||
|
// │ └─detail
|
||||||
|
// │ └─detail.vue
|
||||||
|
const echarts = require('../static/echarts.min.js')
|
||||||
|
|
||||||
|
// ES模块格式
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
```
|
||||||
|
|
||||||
|
> 注意:
|
||||||
|
> - `require` 是小程序平台特有的API,仅在小程序环境下使用
|
||||||
|
> - 路径是相对于当前页面文件的路径,请根据实际项目结构调整路径
|
||||||
|
|
||||||
|
|
||||||
|
## 使用示例 🎯
|
||||||
|
|
||||||
|
### 图表配置项示例
|
||||||
|
|
||||||
|
以下是一个柱状图的配置项示例,在后续使用示例中将引用此配置:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 图表配置项示例 - 柱状图
|
||||||
|
const chartOption = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
},
|
||||||
|
confine: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['热度', '正面', '负面']
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#999999'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666666'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
axisTick: { show: false },
|
||||||
|
data: ['汽车之家', '今日头条', '百度贴吧', '一点资讯', '微信', '微博', '知乎'],
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#999999'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#666666'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '热度',
|
||||||
|
type: 'bar',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'inside'
|
||||||
|
},
|
||||||
|
data: [300, 270, 340, 344, 300, 320, 310]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '正面',
|
||||||
|
type: 'bar',
|
||||||
|
stack: '总量',
|
||||||
|
label: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
data: [120, 102, 141, 174, 190, 250, 220]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '负面',
|
||||||
|
type: 'bar',
|
||||||
|
stack: '总量',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'left'
|
||||||
|
},
|
||||||
|
data: [-20, -32, -21, -34, -90, -130, -110]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> **说明**:在实际项目中,可以根据需求修改上述配置项。
|
||||||
|
> - 更多配置选项请参考 [ECharts 官方文档](https://echarts.apache.org/zh/option.html)
|
||||||
|
> - 查看更多图表样式请访问 [ECharts 官方示例](https://echarts.apache.org/examples/zh/index.html)
|
||||||
|
|
||||||
|
### uni-app 使用方式
|
||||||
|
|
||||||
|
#### 组合式 API 方式
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<view style="width: 750rpx; height: 750rpx;">
|
||||||
|
<l-echart ref="chartRef" @finished="initChart"></l-echart>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const chartRef = ref(null)
|
||||||
|
|
||||||
|
// 仅在小程序环境下引入 ECharts
|
||||||
|
// #ifdef MP
|
||||||
|
const echarts = require('../../static/echarts.min.js') // 根据实际路径调整
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
const echarts = null // H5 和 App 环境不需要手动引入
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 使用上面定义的图表配置项
|
||||||
|
const option = chartOption
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = async () => {
|
||||||
|
if (!chartRef.value) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chart = await chartRef.value.init(echarts)
|
||||||
|
chart.setOption(option)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('图表初始化失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 选项式 API 方式
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<view style="width: 750rpx; height: 750rpx;">
|
||||||
|
<l-echart ref="chartRef" @finished="initChart"></l-echart>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 仅在小程序环境下引入 ECharts
|
||||||
|
// #ifdef MP
|
||||||
|
const echarts = require('../../static/echarts.min.js') // 根据实际路径调整
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
const echarts = null // H5 和 App 环境不需要手动引入
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 使用上面定义的图表配置项
|
||||||
|
option: chartOption,
|
||||||
|
// 图表实例,用于后续操作
|
||||||
|
chartInstance: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 初始化图表
|
||||||
|
async initChart() {
|
||||||
|
if (!this.$refs.chartRef) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.chartInstance = await this.$refs.chartRef.init(echarts)
|
||||||
|
this.chartInstance.setOption(this.option)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('图表初始化失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 更新图表数据
|
||||||
|
updateChart(newOption) {
|
||||||
|
if (this.chartInstance) {
|
||||||
|
this.chartInstance.setOption(newOption)
|
||||||
|
} else if (this.$refs.chartRef) {
|
||||||
|
this.$refs.chartRef.setOption(newOption)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 调整图表大小
|
||||||
|
resizeChart() {
|
||||||
|
if (this.$refs.chartRef) {
|
||||||
|
this.$refs.chartRef.resize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 页面卸载时销毁图表实例
|
||||||
|
beforeUnmount() {
|
||||||
|
if (this.$refs.chartRef) {
|
||||||
|
this.$refs.chartRef.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### uni-app-x 使用方式
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<view style="width: 100%; height: 408px;">
|
||||||
|
<l-echart ref="chartRef" @finished="initChart"></l-echart>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const chartRef = ref<LEchartComponentPublicInstance | null>(null)
|
||||||
|
|
||||||
|
// 仅在小程序环境下引入 ECharts
|
||||||
|
// #ifdef MP
|
||||||
|
const echarts = require('../../static/echarts.min.js') // 根据实际路径调整
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP
|
||||||
|
const echarts = null
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 使用上面定义的图表配置项
|
||||||
|
const option = chartOption
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = async () => {
|
||||||
|
if (chartRef.value === null) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chart = await chartRef.value.init(echarts, null)
|
||||||
|
chart.setOption(option)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('图表初始化失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 高级功能 💪
|
||||||
|
|
||||||
|
### 数据更新 🔄
|
||||||
|
|
||||||
|
图表支持动态更新数据,有两种常用方式:
|
||||||
|
|
||||||
|
#### 方式一:通过组件引用更新
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Vue 3 Composition API
|
||||||
|
chartRef.value?.setOption(newOption)
|
||||||
|
|
||||||
|
// Vue 2 Options API
|
||||||
|
this.$refs.chart.setOption(newOption)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方式二:通过图表实例更新
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 在初始化时保存图表实例
|
||||||
|
let chartInstance = null
|
||||||
|
|
||||||
|
const initChart = async () => {
|
||||||
|
if (!chartRef.value) return
|
||||||
|
chartInstance = await chartRef.value.init(echarts)
|
||||||
|
chartInstance.setOption(option)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后续更新数据
|
||||||
|
const updateChart = () => {
|
||||||
|
if (chartInstance) {
|
||||||
|
chartInstance.setOption(newData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 图表大小调整 📏
|
||||||
|
|
||||||
|
当容器大小改变时,可以调用 `resize` 方法重新调整图表尺寸:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 自动适应容器大小
|
||||||
|
chartRef.value?.resize()
|
||||||
|
|
||||||
|
// 手动指定尺寸
|
||||||
|
chartRef.value?.resize({
|
||||||
|
width: 375, // 像素值
|
||||||
|
height: 375 // 像素值
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**💡 提示**:在窗口大小变化或屏幕旋转时,可以监听相应事件并调用 `resize` 方法。
|
||||||
|
|
||||||
|
### Vue 2 兼容配置 🔄
|
||||||
|
|
||||||
|
如果您的项目使用 Vue 2,需要先安装并引入 Vue Composition API:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// main.js
|
||||||
|
import Vue from 'vue'
|
||||||
|
import VueCompositionAPI from '@vue/composition-api'
|
||||||
|
Vue.use(VueCompositionAPI)
|
||||||
|
```
|
||||||
|
|
||||||
|
详细配置请参考:[Vue Composition API 官方文档](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)
|
||||||
|
|
||||||
|
### 组件标签说明 🏷️
|
||||||
|
|
||||||
|
| 标签名 | 说明 |
|
||||||
|
|-------|------|
|
||||||
|
| `l-echart` | 正式使用的组件标签 |
|
||||||
|
| `lime-echart` | 演示用组件标签 |
|
||||||
|
|
||||||
|
### 快速预览 🚀
|
||||||
|
|
||||||
|
导入插件后,可以直接使用演示标签查看效果:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<view style="width: 100%; height: 400px;">
|
||||||
|
<!-- 演示组件 -->
|
||||||
|
<lime-echart />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题与解决方案 🐛
|
||||||
|
|
||||||
|
### 平台特殊问题
|
||||||
|
|
||||||
|
#### 微信小程序
|
||||||
|
- **画布层级问题**:微信开发工具中 canvas 可能出现层级过高或不跟随页面滚动的情况,真机环境下通常不受影响
|
||||||
|
- **Tooltip 阴影**:如需去除文字阴影,可添加配置:`tooltip.shadowBlur = 0`
|
||||||
|
|
||||||
|
#### 钉钉小程序
|
||||||
|
- **文字测量精度**:由于钉钉小程序没有原生 `measureText`,字体粗细测量可能不够精确
|
||||||
|
- **安全扫描警告**:如遇到 `Uint8Clamped` 安全问题,可按以下方式修改 ECharts 文件:
|
||||||
|
```js
|
||||||
|
// 查找类似代码并修改
|
||||||
|
// 原代码
|
||||||
|
["Int8","Uint8","Uint8Clamped","Int16","Uint16","Int32","Uint32","Float32","Float64"],(function(t,e){return t["[object "+e+"Array]"]
|
||||||
|
// 修改为
|
||||||
|
["Int8","Uint8","Uint8_Clamped","Int16","Uint16","Int32","Uint32","Float32","Float64"],(function(t,e){return t["[object "+e.replace('_','')+"Array]"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 功能限制 ⚠️
|
||||||
|
- **Toolbox**:不支持 `saveImage` 功能
|
||||||
|
- **Lines 图表**:不支持 `trailLength` 属性,请设置为 `0`
|
||||||
|
- **DataZoom**:H5 平台不建议设置 `showDetail` 属性
|
||||||
|
- **自定义 Tooltips**:uvue 和 vue 中不支持 DOM 操作相关的自定义 Tooltips
|
||||||
|
|
||||||
|
## API 参考 📝
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
|
|------|------|------|--------|------|
|
||||||
|
| l-style | 自定义样式 | string | - | - |
|
||||||
|
| type | 指定 canvas 类型(废除) | string | "2d" | - |
|
||||||
|
| is-disable-scroll | 触摸图表时是否禁止页面滚动 | boolean | false | - |
|
||||||
|
| beforeDelay | 延迟初始化时间(毫秒) | number | 30 | - |
|
||||||
|
| enableHover | PC端是否启用鼠标悬浮效果(废除) | boolean | false | - |
|
||||||
|
| landscape | 是否旋转90度,模拟横屏效果 | boolean | false | - |
|
||||||
|
| autoHideTooltip | 是否自动隐藏Tooltip | boolean | false | - |
|
||||||
|
|
||||||
|
### 组件方法
|
||||||
|
|
||||||
|
| 方法名 | 参数 | 返回值 | 说明 |
|
||||||
|
|--------|------|--------|------|
|
||||||
|
| init | `echarts: Object, config?: Object` | `Promise<ChartInstance>` | 初始化图表实例 |
|
||||||
|
| setOption | `option: Object` | `void` | 设置或更新图表配置项 |
|
||||||
|
| resize | `size?: {width: number, height: number}` | `void` | 调整图表尺寸 |
|
||||||
|
| clear | `-` | `void` | 清空图表内容 |
|
||||||
|
| dispose | `-` | `void` | 销毁图表实例 |
|
||||||
|
| showLoading | `-` | `void` | 显示加载动画 |
|
||||||
|
| hideLoading | `-` | `void` | 隐藏加载动画 |
|
||||||
|
| canvasToTempFilePath | `options: Object` | `Promise<Object>` | 生成图表图片,与 uni-app 官方 API 类似,但无需传入 canvasId |
|
||||||
|
|
||||||
|
### 事件
|
||||||
|
|
||||||
|
| 事件名 | 参数 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| finished | 无 | 图表准备就绪时触发,此时可调用 init 方法 |
|
||||||
|
|
||||||
|
## 其他平台依赖说明 🌐
|
||||||
|
|
||||||
|
### uni-app 非 nvue 端
|
||||||
|
|
||||||
|
- **推荐使用 `npm` 安装**
|
||||||
|
- 通过 npm 安装可以获得完整的 ES 模块格式支持
|
||||||
|
```bash
|
||||||
|
npm install echarts --save
|
||||||
|
```
|
||||||
|
- 安装后可直接在代码中通过 `import` 引入
|
||||||
|
```js
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
```
|
||||||
|
|
||||||
|
### uni-app-x 非 App 端
|
||||||
|
|
||||||
|
- **推荐使用 npm 安装**获取 ES 模块格式
|
||||||
|
```bash
|
||||||
|
npm install echarts --save
|
||||||
|
```
|
||||||
|
- ES 模块格式具有更好的性能和构建优化支持
|
||||||
|
- 通过 `import` 引入使用
|
||||||
|
```js
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
```
|
||||||
|
|
||||||
|
> 💡 注意:H5 和 App 原生环境通常不需要手动引入 ECharts,组件会自动处理。只有在需要自定义 ECharts 版本或配置时才需要手动引入。
|
||||||
|
|
||||||
|
## 技术支持 🆘
|
||||||
|
|
||||||
|
如果您在使用过程中遇到问题,可以通过以下方式获取帮助:
|
||||||
|
|
||||||
|
1. 查看 [在线文档](https://limeui.qcoon.cn/#/echart) 获取详细使用说明
|
||||||
|
2. 检查 [常见问题](#常见问题与解决方案) 章节查找解决方案
|
||||||
|
|
||||||
|
## 贡献与支持 💙
|
||||||
|
|
||||||
|
如果您觉得本插件对您有帮助,欢迎给作者点个赞或提供支持:
|
||||||
|
|
||||||
|
| 支付宝 | 微信 |
|
||||||
|
|--------|------|
|
||||||
|
|  |  |
|
||||||
|
|
||||||
|
您的支持是作者持续开发和维护的动力! 🌟
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,184 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title></title>
|
||||||
|
<style type="text/css">
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
/* 隐藏滚动条 */
|
||||||
|
overscroll-behavior: none;
|
||||||
|
/* 禁止橡皮筋效果 */
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
.canvas {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
background-color: transparent;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="canvas" id="limeChart"></div>
|
||||||
|
<script type="text/javascript" src="./uni.webview.1.5.5.js"></script>
|
||||||
|
<script type="text/javascript" src="./echarts.min.js"></script>
|
||||||
|
<script type="text/javascript" src="./ecStat.min.js"></script>
|
||||||
|
<!-- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-liquidfill@latest/dist/echarts-liquidfill.min.js"></script> -->
|
||||||
|
<script>
|
||||||
|
let chart = null;
|
||||||
|
let cache = [];
|
||||||
|
console.log = function() {
|
||||||
|
emit('log', {
|
||||||
|
log: arguments,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function emit(event, data) {
|
||||||
|
postMessage({
|
||||||
|
event,
|
||||||
|
data
|
||||||
|
})
|
||||||
|
cache = []
|
||||||
|
}
|
||||||
|
|
||||||
|
function postMessage(data) {
|
||||||
|
uni.webView.postMessage({
|
||||||
|
data
|
||||||
|
})
|
||||||
|
// window.__uniapp_x_.postMessage(JSON.stringify(data))
|
||||||
|
};
|
||||||
|
|
||||||
|
function stringify(key, value) {
|
||||||
|
if (typeof value === 'object' && value !== null) {
|
||||||
|
if (cache.indexOf(value) !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cache.push(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(name, callback, options) {
|
||||||
|
const optionNameReg = /[\w]+\.setOption\(([\w]+\.)?([\w]+)\)/
|
||||||
|
if (optionNameReg.test(callback)) {
|
||||||
|
const optionNames = callback.match(optionNameReg)
|
||||||
|
if (optionNames[1]) {
|
||||||
|
const _this = optionNames[1].split('.')[0]
|
||||||
|
window[_this] = {}
|
||||||
|
window[_this][optionNames[2]] = options
|
||||||
|
return optionNames[2]
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(callback, options, opts, theme) {
|
||||||
|
if (!chart) {
|
||||||
|
chart = echarts.init(document.getElementById('limeChart'), theme, opts)
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
chart.setOption(options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function on(data) {
|
||||||
|
if (chart && data.length > 0) {
|
||||||
|
const [type, query] = data
|
||||||
|
const key = `${type}${JSON.stringify(query||'')}`
|
||||||
|
if (query) {
|
||||||
|
chart.on(type, query, function(options) {
|
||||||
|
var obj = {};
|
||||||
|
Object.keys(options).forEach(function(key) {
|
||||||
|
if (key != 'event') {
|
||||||
|
obj[key] = options[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit(key, {
|
||||||
|
event: key,
|
||||||
|
options: obj,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
chart.on(type, function(options) {
|
||||||
|
var obj = {};
|
||||||
|
Object.keys(options).forEach(function(key) {
|
||||||
|
if (key != 'event') {
|
||||||
|
obj[key] = options[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
emit(key, {
|
||||||
|
event: key,
|
||||||
|
options: obj,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setChart(callback, options) {
|
||||||
|
if (!callback) return
|
||||||
|
if (chart && callback && options) {
|
||||||
|
var r = null
|
||||||
|
const name = parse('r', callback, options)
|
||||||
|
if (name) this[name] = options
|
||||||
|
eval(`r = ${callback};`)
|
||||||
|
if (r) {
|
||||||
|
r(chart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setOption(data) {
|
||||||
|
if (chart) chart.setOption(data[0], data[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
function showLoading(data) {
|
||||||
|
if (chart) chart.showLoading(data[0], data[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideLoading() {
|
||||||
|
if (chart) chart.hideLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
if (chart) chart.clear()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function dispose() {
|
||||||
|
if (chart) chart.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
function resize(size) {
|
||||||
|
if (chart) chart.resize(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
function canvasToTempFilePath(opt) {
|
||||||
|
if (chart) {
|
||||||
|
delete opt.success
|
||||||
|
const src = chart.getDataURL(opt)
|
||||||
|
postMessage({
|
||||||
|
// event: 'file',
|
||||||
|
file: src
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('touchmove', () => {
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue