echarts插件更换
parent
bdc3839df6
commit
87328bf217
|
@ -8,7 +8,7 @@ image{
|
||||||
}
|
}
|
||||||
.main{
|
.main{
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
min-height: 1920px;
|
min-height: 100vh;
|
||||||
background-image: url('/static/page-bg.jpg');
|
background-image: url('/static/page-bg.jpg');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name" : "碳中和",
|
"name" : "碳足迹计算器",
|
||||||
"appid" : "__UNI__DB95977",
|
"appid" : "__UNI__DB95977",
|
||||||
"description" : "",
|
"description" : "",
|
||||||
"versionName" : "1.0.0",
|
"versionName" : "1.0.0",
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
</view>
|
</view>
|
||||||
<!-- 饼图 -->
|
<!-- 饼图 -->
|
||||||
<view class="pie-chart">
|
<view class="pie-chart">
|
||||||
<uni-chart :option="pie" />
|
<l-echart ref="chart" @finished="init"></l-echart>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="assess-title">
|
<view class="assess-title">
|
||||||
|
@ -142,6 +142,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import swiperPull from '@/components/swiper/swiper-pull.vue';
|
import swiperPull from '@/components/swiper/swiper-pull.vue';
|
||||||
|
import * as echarts from '@/uni_modules/lime-echart/static/echarts.min.js';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
swiperPull
|
swiperPull
|
||||||
|
@ -180,7 +181,17 @@
|
||||||
// 绘制饼图
|
// 绘制饼图
|
||||||
this.pieEv();
|
this.pieEv();
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$refs.chart.init(echarts, chart => {
|
||||||
|
chart.setOption(this.pie);
|
||||||
|
});
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.$refs.chart.init(echarts, chart => {
|
||||||
|
chart.setOption(this.pie);
|
||||||
|
});
|
||||||
|
},
|
||||||
// 绘制饼图
|
// 绘制饼图
|
||||||
pieEv() {
|
pieEv() {
|
||||||
this.pie = {
|
this.pie = {
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2022 xbmlz
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,166 +0,0 @@
|
||||||
# 在 uni-app 中使用 Apache ECharts
|
|
||||||
|
|
||||||
本项目是 [Apache ECharts](https://github.com/apache/echarts) 的uni-app版本,支持 [Vue.js](https://vuejs.org/) 2/3,以及使用的示例。
|
|
||||||
|
|
||||||
开发者可以通过熟悉的 ECharts 配置方式,快速开发图表,满足各种可视化需求.
|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
|
|
||||||
### 方式一: 使用 uni_modules 安装(推荐)
|
|
||||||
|
|
||||||
使用 `uni_modules` 方式安装组件库,可以直接通过插件市场导入,通过右键菜单快速更新组件,不需要引用、注册,直接在页面中使用 `echarts-for-uniapp` 组件。[点击安装 echarts-for-uniapp 组件库](https://ext.dcloud.net.cn/plugin?name=echarts-for-uniapp)
|
|
||||||
|
|
||||||
### 方式二: 使用 npm 安装
|
|
||||||
|
|
||||||
在 `vue-cli` 项目中可以使用 `npm` 安装 `echarts-for-uniapp` 库 ,或者直接在 `HBuilderX` 项目中使用 `npm` 。(不推荐后一种方式)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm i uniapp-echarts
|
|
||||||
```
|
|
||||||
|
|
||||||
### 创建图表
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<view class="content">
|
|
||||||
<uni-chart :option="option" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
option: {
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: [120, 200, 150, 80, 70, 110, 130],
|
|
||||||
type: 'bar',
|
|
||||||
showBackground: true,
|
|
||||||
backgroundStyle: {
|
|
||||||
color: 'rgba(180, 180, 180, 0.2)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.content {
|
|
||||||
width: 375px;
|
|
||||||
height: 375px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
这对于所有 ECharts 图表都是通用的,用户只需要修改上面 `option` 的内容,即可改变图表。`option` 的使用方法参见 [ECharts 配置项文档](https://echarts.apache.org/zh/option.html)。对于不熟悉 ECharts 的用户,可以参见 [5 分钟上手 ECharts](https://echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts) 教程。
|
|
||||||
|
|
||||||
完整的例子请参见 [xbmlz/echarts-for-uniapp](https://github.com/xbmlz/echarts-for-uniapp) 项目。
|
|
||||||
|
|
||||||
|
|
||||||
### 支持平台
|
|
||||||
|
|
||||||
| Vue2 | Vue3 |
|
|
||||||
| --- | --- |
|
|
||||||
| ✔️ | ✔️ |
|
|
||||||
|
|
||||||
|
|
||||||
| APP-VUE | APP-NVUE | 小程序 | WEB/H5 |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| ✔️ | ❌ | ✔ | ✔ |
|
|
||||||
|
|
||||||
### 参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 默认值 | 描述 |
|
|
||||||
| :--: | :--: | :--: | :-- |
|
|
||||||
| forceUseOldCanvas | Boolean | false | 强制使用旧版Canvas(不推荐) |
|
|
||||||
| option | Object | | [ECharts Option](https://echarts.apache.org/zh/option.html) |
|
|
||||||
| theme | String| | [Eharts Theme](https://echarts.apache.org/zh/download-theme.html) |
|
|
||||||
| map | Object| | 使用地图组件时,注册地图,详见:[registerMap](https://echarts.apache.org/en/api.html#echarts.registerMap) |
|
|
||||||
|
|
||||||
|
|
||||||
### 事件
|
|
||||||
|
|
||||||
| 事件名 | 参数 | 返回数据 | 描述 |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| inited | | chart | 初始化后返回 chart 对象 |
|
|
||||||
| click | | event | 点击 |
|
|
||||||
| touchstart | | event | 按下 |
|
|
||||||
| touchmove | | event | 移动 |
|
|
||||||
| touchend | | event | 松开 |
|
|
||||||
| mousedown | | event | 按下 |
|
|
||||||
| mousemove | | event | 移动 |
|
|
||||||
| mouseup | | event | 松开 |
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
### 如何获取图表实例?
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<view class="content">
|
|
||||||
<uni-chart @inited="inited" />
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
inited(chart) {
|
|
||||||
// do something
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 如何延迟加载图表?
|
|
||||||
|
|
||||||
参见 [pages/lazyLoad](./pages/lazyLoad/index.vue) 的例子,可以在获取数据后再初始化数据。
|
|
||||||
|
|
||||||
### 如何在一个页面中加载多个图表?
|
|
||||||
|
|
||||||
参见 [pages/multiCharts](./pages/multiCharts/index.vue) 的例子。
|
|
||||||
|
|
||||||
### 如何使用 Tooltip?
|
|
||||||
|
|
||||||
具体使用方法和 ECharts 相同,例子参见 [pages/line](./pages/line/index.vue)
|
|
||||||
|
|
||||||
### 如何保存为图片?
|
|
||||||
|
|
||||||
参见 [pages/saveCanvas](./pages/saveCanvas/index.vue) 的例子。
|
|
||||||
|
|
||||||
### 多主题色
|
|
||||||
|
|
||||||
参见 [pages/themeColor](./pages/themeColor/index.vue) 的例子 。
|
|
||||||
|
|
||||||
### 完整示例
|
|
||||||
|
|
||||||
参见 [pages](./pages)
|
|
||||||
|
|
||||||
### 文件太大怎么办?
|
|
||||||
|
|
||||||
本项目默认提供的 ECharts 文件是最新版本的包含所有组件文件。可以下载不同版本的 [ECharts](https://github.com/apache/echarts/blob/master/dist/) 进行替换。建议调试时使用未压缩版本,发布时使用压缩版本,否则文件会太大无法发布。
|
|
||||||
|
|
||||||
发布时,如果对文件大小要求更高,可以在 [ECharts 在线定制](https://echarts.apache.org/zh/builder.html)网页下载仅包含必要组件的包,并且选择压缩。
|
|
||||||
|
|
||||||
下载的文件放在 `uni_modules/echarts-for-uniapp/static/echarts.min.js`,**注意一定需要重命名为 `echarts.min.js`**。
|
|
||||||
|
|
||||||
此外,还可考虑使用微信小程序的[分包策略](https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/independent.html)
|
|
||||||
|
|
||||||
|
|
||||||
如有其它问题,也欢迎在 [issue](https://github.com/xbmlz/echarts-for-uniapp/issues) 中反馈,谢谢!
|
|
|
@ -1,17 +0,0 @@
|
||||||
## 1.0.2(2022-11-20)
|
|
||||||
- 新增 `pages` 文件夹下新增组件示例
|
|
||||||
- 新增 保存到相册方法
|
|
||||||
- 新增 地图注册方法
|
|
||||||
- 新增 多主题色功能
|
|
||||||
- 修复 修复点击事件报错
|
|
||||||
- 优化 优化部分细节
|
|
||||||
## 1.0.1(2022-11-20)
|
|
||||||
- 新增 支持vue2.x, 旧版微信小程序
|
|
||||||
- 新增 h5点击事件
|
|
||||||
- 新增 小程序触摸事件
|
|
||||||
- 新增 forceUseOldCanvas参数:强制使用旧版Canvas
|
|
||||||
- 移除 width、height属性,用style代替
|
|
||||||
|
|
||||||
## 1.0.0(2022-11-18)
|
|
||||||
|
|
||||||
- 在uni-app中可以以组件的形式使用 ECharts, 支持touch事件。
|
|
|
@ -1,3 +0,0 @@
|
||||||
<template>
|
|
||||||
<view></view>
|
|
||||||
</template>
|
|
|
@ -1,106 +0,0 @@
|
||||||
export class UniCanvas {
|
|
||||||
|
|
||||||
constructor(ctx, canvasNode) {
|
|
||||||
this.ctx = ctx
|
|
||||||
this.chart = {}
|
|
||||||
this.canvasNode = canvasNode
|
|
||||||
if (!canvasNode) {
|
|
||||||
this._initStyle(ctx)
|
|
||||||
}
|
|
||||||
this._initEvent()
|
|
||||||
}
|
|
||||||
|
|
||||||
getContext(contextType) {
|
|
||||||
if (contextType === '2d') {
|
|
||||||
return this.ctx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setChart(chart) {
|
|
||||||
this.chart = chart
|
|
||||||
}
|
|
||||||
|
|
||||||
attachEvent() {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
detachEvent() {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener() {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
removeEventListener() {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
_initCanvas(zrender, ctx) {
|
|
||||||
zrender.util.getContext = () => {
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
zrender.util.$override('measureText', (text, font) => {
|
|
||||||
ctx.font = font || '12px sans-serif'
|
|
||||||
return ctx.measureText(text)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_initStyle(ctx) {
|
|
||||||
ctx.createCircularGradient = (x, y, r) => {
|
|
||||||
return ctx.createCircularGradient(x, y, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_initEvent() {
|
|
||||||
this.event = {}
|
|
||||||
const eventNames = [{
|
|
||||||
wxName: 'touchStart',
|
|
||||||
ecName: 'mousedown',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
wxName: 'touchMove',
|
|
||||||
ecName: 'mousemove',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
wxName: 'touchEnd',
|
|
||||||
ecName: 'mouseup',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
wxName: 'touchEnd',
|
|
||||||
ecName: 'click',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
eventNames.forEach((name) => {
|
|
||||||
this.event[name.wxName] = (e) => {
|
|
||||||
const touch = e.touches[0]
|
|
||||||
this.chart.getZr().handler.dispatch(name.ecName, {
|
|
||||||
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
|
|
||||||
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
|
|
||||||
preventDefault: () => {},
|
|
||||||
stopImmediatePropagation: () => {},
|
|
||||||
stopPropagation: () => {},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
get width() {
|
|
||||||
if (this.canvasNode) return this.canvasNode.width
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
set width(w) {
|
|
||||||
if (this.canvasNode) this.canvasNode.width = w
|
|
||||||
}
|
|
||||||
|
|
||||||
get height() {
|
|
||||||
if (this.canvasNode) return this.canvasNode.height
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
set height(h) {
|
|
||||||
if (this.canvasNode) this.canvasNode.height = h
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,351 +0,0 @@
|
||||||
<template>
|
|
||||||
<!-- #ifdef APP-VUE || H5 -->
|
|
||||||
<view v-if="systemInfo.deviceType === 'pc'" :id="canvasId" class="uni-canvas" @click="emits('click', $event)" />
|
|
||||||
<view
|
|
||||||
v-else
|
|
||||||
:id="canvasId"
|
|
||||||
class="uni-canvas"
|
|
||||||
@click="click"
|
|
||||||
@touchstart="touchStart"
|
|
||||||
@touchmove.stop="touchMove"
|
|
||||||
@touchend="touchEnd"
|
|
||||||
/>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- #ifdef MP-WEIXIN || MP-QQ -->
|
|
||||||
<canvas
|
|
||||||
v-if="useNewCanvas"
|
|
||||||
type="2d"
|
|
||||||
:id="canvasId"
|
|
||||||
class="uni-canvas"
|
|
||||||
:canvas-id="canvasId"
|
|
||||||
@click="click"
|
|
||||||
@touchstart="touchStart"
|
|
||||||
@touchmove.stop="touchMove"
|
|
||||||
@touchend="touchEnd"
|
|
||||||
/>
|
|
||||||
<canvas
|
|
||||||
v-else
|
|
||||||
:id="canvasId"
|
|
||||||
class="uni-canvas"
|
|
||||||
:canvas-id="canvasId"
|
|
||||||
@click="click"
|
|
||||||
@touchstart="touchStart"
|
|
||||||
@touchmove.stop="touchMove"
|
|
||||||
@touchend="touchEnd"
|
|
||||||
/>
|
|
||||||
<!-- #endif -->
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// #ifdef VUE3
|
|
||||||
import '../../static/echarts.min.js'
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef VUE2 || MP-WEIXIN
|
|
||||||
const echarts = require('../../static/echarts.min.js')
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
import { UniCanvas } from './uni-canvas.js'
|
|
||||||
|
|
||||||
let chart = null
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'uni-chart',
|
|
||||||
emits: ['inited', 'click', 'touchStart', 'touchMove', 'touchEnd'],
|
|
||||||
props: {
|
|
||||||
// 是否强制使用旧版本 canvas 绘制(不推荐)
|
|
||||||
forceUseOldCanvas: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 主题名称,内置
|
|
||||||
theme: {
|
|
||||||
type: [String, Object],
|
|
||||||
},
|
|
||||||
// 图表配置
|
|
||||||
option: {
|
|
||||||
type: Object,
|
|
||||||
require: true,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 地图注册配置
|
|
||||||
map: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
canvasId: `uni-canvas-${Date.now()}`,
|
|
||||||
systemInfo: uni.getSystemInfoSync(),
|
|
||||||
useNewCanvas: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.registerPreprocessor()
|
|
||||||
this.registerMap()
|
|
||||||
this.$nextTick(() => {
|
|
||||||
// #ifdef APP-VUE || H5
|
|
||||||
this.initH5()
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN || MP-QQ
|
|
||||||
this.initMiniProgram()
|
|
||||||
// #endif
|
|
||||||
})
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
this.dispose()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// register echarts preprocessor
|
|
||||||
registerPreprocessor() {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// register geo json
|
|
||||||
registerMap() {
|
|
||||||
if (JSON.stringify(this.$props.map) === '{}') return
|
|
||||||
echarts.registerMap(this.$props.map.name, this.$props.map.opt)
|
|
||||||
},
|
|
||||||
// register theme color
|
|
||||||
registerTheme(name, opt) {
|
|
||||||
console.log('registerTheme', name, opt)
|
|
||||||
echarts.registerTheme(name, opt)
|
|
||||||
},
|
|
||||||
// init H5 app-vue
|
|
||||||
initH5() {
|
|
||||||
const canvasNode = document.getElementById(this.canvasId)
|
|
||||||
chart = echarts.init(canvasNode, this.$props.theme)
|
|
||||||
this.$emit('inited', chart)
|
|
||||||
chart.setOption(this.$props.option)
|
|
||||||
},
|
|
||||||
// init mini program
|
|
||||||
initMiniProgram() {
|
|
||||||
const version = this.systemInfo.SDKVersion
|
|
||||||
console.log(`当前基础库版本为: ${version}`)
|
|
||||||
|
|
||||||
const oldVersion = '1.9.91'
|
|
||||||
const baseVersion = '2.9.0'
|
|
||||||
|
|
||||||
let canUseNewCanvas = this.compareVersion(version, baseVersion) >= 0
|
|
||||||
|
|
||||||
if (this.$props.forceUseOldCanvas) {
|
|
||||||
if (canUseNewCanvas) console.warn('开发者强制使用旧canvas,建议关闭')
|
|
||||||
canUseNewCanvas = false
|
|
||||||
}
|
|
||||||
this.useNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas
|
|
||||||
if (this.useNewCanvas) {
|
|
||||||
// 2.9.0 可以使用 <canvas type="2d"></canvas>
|
|
||||||
this.initNewCanvas()
|
|
||||||
} else {
|
|
||||||
const isValid = this.compareVersion(version, oldVersion) >= 0
|
|
||||||
if (!isValid) {
|
|
||||||
console.error(`基础库版本过低,需大于等于 ${oldVersion}。`)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
console.warn(`建议将基础库调整大于等于${baseVersion}版本。升级后绘图将有更好性能`)
|
|
||||||
this.initOldCanvas()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// initNewCanvas
|
|
||||||
initNewCanvas() {
|
|
||||||
const query = uni.createSelectorQuery().in(this)
|
|
||||||
query
|
|
||||||
.select(`#${this.canvasId}`)
|
|
||||||
.node(res => {
|
|
||||||
const canvasNode = res.node
|
|
||||||
const ctx = canvasNode?.getContext('2d')
|
|
||||||
canvasNode.width = canvasNode.width * this.systemInfo.pixelRatio
|
|
||||||
canvasNode.height = canvasNode.height * this.systemInfo.pixelRatio
|
|
||||||
ctx.scale(this.pixelRatio, this.pixelRatio)
|
|
||||||
const canvas = new UniCanvas(ctx, canvasNode)
|
|
||||||
this.initECharts(canvas, canvasNode.width, canvasNode.width, this.pixelRatio)
|
|
||||||
})
|
|
||||||
.exec()
|
|
||||||
},
|
|
||||||
// initOldCanvas
|
|
||||||
initOldCanvas() {
|
|
||||||
// 1.9.91 <= sdkVersion < 2.9.0:原来的方式初始化
|
|
||||||
const ctx = uni.createCanvasContext(`#${this.canvasId}`, this)
|
|
||||||
const canvas = new UniCanvas(ctx)
|
|
||||||
const query = uni.createSelectorQuery().in(this)
|
|
||||||
query
|
|
||||||
.select(`#${this.canvasId}`)
|
|
||||||
.boundingClientRect(res => {
|
|
||||||
// 微信旧的canvas不能传入dpr
|
|
||||||
this.initECharts(res.width, res.height, 1)
|
|
||||||
})
|
|
||||||
.exec()
|
|
||||||
},
|
|
||||||
// init
|
|
||||||
initECharts(canvas, width, height, dpr) {
|
|
||||||
echarts.setPlatformAPI({ createCanvas: () => canvas })
|
|
||||||
const theme = this.$props.theme
|
|
||||||
let themeName = ''
|
|
||||||
console.log('typeof theme', typeof theme)
|
|
||||||
if (typeof theme === 'object') {
|
|
||||||
this.registerTheme(theme.name, theme.opt)
|
|
||||||
themeName = theme.name
|
|
||||||
}
|
|
||||||
if (typeof theme === 'string') {
|
|
||||||
themeName = theme
|
|
||||||
}
|
|
||||||
chart = echarts.init(canvas, themeName, {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
devicePixelRatio: dpr
|
|
||||||
})
|
|
||||||
this.$emit('inited', chart)
|
|
||||||
this.setOption(this.$props.option)
|
|
||||||
},
|
|
||||||
canvasToTempFilePath(opt) {
|
|
||||||
if (this.useNewCanvas) {
|
|
||||||
const query = uni.createSelectorQuery().in(this)
|
|
||||||
query
|
|
||||||
.select(`#${this.canvasId}`)
|
|
||||||
.node(res => {
|
|
||||||
const canvasNode = res.node
|
|
||||||
opt.canvas = canvasNode
|
|
||||||
uni.canvasToTempFilePath(opt)
|
|
||||||
})
|
|
||||||
.exec()
|
|
||||||
} else {
|
|
||||||
if (!opt.canvasId) {
|
|
||||||
opt.canvasId = this.canvasId
|
|
||||||
}
|
|
||||||
// TODO
|
|
||||||
chart.ctx.draw(true, () => {
|
|
||||||
uni.canvasToTempFilePath(opt, this)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setOption(opt) {
|
|
||||||
chart.setOption(opt)
|
|
||||||
},
|
|
||||||
dispose() {
|
|
||||||
chart && chart.dispose()
|
|
||||||
},
|
|
||||||
// event
|
|
||||||
wrapTouch(event) {
|
|
||||||
for (let i = 0; i < event.touches.length; ++i) {
|
|
||||||
const touch = event.touches[i]
|
|
||||||
touch.offsetX = touch.x
|
|
||||||
touch.offsetY = touch.y
|
|
||||||
}
|
|
||||||
return event
|
|
||||||
},
|
|
||||||
click(e) {
|
|
||||||
this.$emit('click', e)
|
|
||||||
},
|
|
||||||
touchStart(e) {
|
|
||||||
if (chart && e.touches.length > 0) {
|
|
||||||
const touch = e.touches[0]
|
|
||||||
const handler = chart.getZr().handler
|
|
||||||
handler.dispatch('mousedown', {
|
|
||||||
zrX: touch.x,
|
|
||||||
zrY: touch.y,
|
|
||||||
preventDefault: () => {},
|
|
||||||
stopPropagation: () => {}
|
|
||||||
})
|
|
||||||
handler.dispatch('mousemove', {
|
|
||||||
zrX: touch.x,
|
|
||||||
zrY: touch.y,
|
|
||||||
preventDefault: () => {},
|
|
||||||
stopPropagation: () => {}
|
|
||||||
})
|
|
||||||
handler.processGesture(this.wrapTouch(e), 'start')
|
|
||||||
this.$emit('touchStart', e)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchMove(e) {
|
|
||||||
if (chart && e.touches.length > 0) {
|
|
||||||
let touch = e.touches[0]
|
|
||||||
const {
|
|
||||||
target: { offsetLeft, offsetTop }
|
|
||||||
} = e
|
|
||||||
touch.x = touch.pageX - offsetLeft
|
|
||||||
touch.y = touch.pageY - offsetTop
|
|
||||||
const handler = chart.getZr().handler
|
|
||||||
if (handler) {
|
|
||||||
handler.dispatch('mousemove', {
|
|
||||||
zrX: touch.x,
|
|
||||||
zrY: touch.y
|
|
||||||
})
|
|
||||||
handler.processGesture(this.wrapTouch(e), 'change')
|
|
||||||
}
|
|
||||||
this.$emit('touchMove', e)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchEnd(e) {
|
|
||||||
if (chart) {
|
|
||||||
const touch = e.changedTouches ? e.changedTouches[0] : {}
|
|
||||||
const {
|
|
||||||
target: { offsetLeft, offsetTop }
|
|
||||||
} = e
|
|
||||||
touch.x = touch.pageX - offsetLeft
|
|
||||||
touch.y = touch.pageY - offsetTop
|
|
||||||
var handler = chart.getZr().handler
|
|
||||||
if (handler) {
|
|
||||||
handler.dispatch('mouseup', {
|
|
||||||
zrX: touch.x,
|
|
||||||
zrY: touch.y
|
|
||||||
})
|
|
||||||
handler.dispatch('click', {
|
|
||||||
zrX: touch.x,
|
|
||||||
zrY: touch.y
|
|
||||||
})
|
|
||||||
handler.processGesture(this.wrapTouch(e), 'end')
|
|
||||||
}
|
|
||||||
this.$emit('touchEnd', e)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// utils
|
|
||||||
compareVersion(v1, v2) {
|
|
||||||
v1 = v1.split('.')
|
|
||||||
v2 = v2.split('.')
|
|
||||||
const len = Math.max(v1.length, v2.length)
|
|
||||||
|
|
||||||
while (v1.length < len) {
|
|
||||||
v1.push('0')
|
|
||||||
}
|
|
||||||
while (v2.length < len) {
|
|
||||||
v2.push('0')
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
const num1 = parseInt(v1[i])
|
|
||||||
const num2 = parseInt(v2[i])
|
|
||||||
if (num1 > num2) {
|
|
||||||
return 1
|
|
||||||
} else if (num1 < num2) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
.uni-canvas {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,89 +0,0 @@
|
||||||
{
|
|
||||||
"id": "echarts-for-uniapp",
|
|
||||||
"name": "uniapp-echarts",
|
|
||||||
"displayName": "echarts-for-uniapp",
|
|
||||||
"version": "1.0.2",
|
|
||||||
"description": "uni-app 版本 echarts, 支持 Vue2/3, 开发者可以通过熟悉的 ECharts 配置方式,快速开发图表,满足各种可视化需求.",
|
|
||||||
"keywords": [
|
|
||||||
"echarts-uniapp",
|
|
||||||
"echarts",
|
|
||||||
"echarts",
|
|
||||||
"图表",
|
|
||||||
"可视化"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"release": "bumpp && npm publish"
|
|
||||||
},
|
|
||||||
"repository": "https://github.com/xbmlz/echarts-for-uniapp",
|
|
||||||
"engines": {
|
|
||||||
"HBuilderX": "^3.2.13"
|
|
||||||
},
|
|
||||||
"dcloudext": {
|
|
||||||
"type": "component-vue",
|
|
||||||
"sale": {
|
|
||||||
"regular": {
|
|
||||||
"price": "0.00"
|
|
||||||
},
|
|
||||||
"sourcecode": {
|
|
||||||
"price": "0.00"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"contact": {
|
|
||||||
"qq": "997909544"
|
|
||||||
},
|
|
||||||
"declaration": {
|
|
||||||
"ads": "无",
|
|
||||||
"data": "插件不采集任何数据",
|
|
||||||
"permissions": "无"
|
|
||||||
},
|
|
||||||
"npmurl": "https://www.npmjs.com/package/echarts-for-uniapp"
|
|
||||||
},
|
|
||||||
"uni_modules": {
|
|
||||||
"dependencies": [],
|
|
||||||
"encrypt": [],
|
|
||||||
"platforms": {
|
|
||||||
"cloud": {
|
|
||||||
"tcb": "y",
|
|
||||||
"aliyun": "y"
|
|
||||||
},
|
|
||||||
"client": {
|
|
||||||
"Vue": {
|
|
||||||
"vue2": "y",
|
|
||||||
"vue3": "y"
|
|
||||||
},
|
|
||||||
"App": {
|
|
||||||
"app-vue": "y",
|
|
||||||
"app-nvue": "u"
|
|
||||||
},
|
|
||||||
"H5-mobile": {
|
|
||||||
"Safari": "y",
|
|
||||||
"Android Browser": "y",
|
|
||||||
"微信浏览器(Android)": "y",
|
|
||||||
"QQ浏览器(Android)": "y"
|
|
||||||
},
|
|
||||||
"H5-pc": {
|
|
||||||
"Chrome": "y",
|
|
||||||
"IE": "u",
|
|
||||||
"Edge": "y",
|
|
||||||
"Firefox": "y",
|
|
||||||
"Safari": "y"
|
|
||||||
},
|
|
||||||
"小程序": {
|
|
||||||
"微信": "y",
|
|
||||||
"阿里": "u",
|
|
||||||
"百度": "u",
|
|
||||||
"字节跳动": "u",
|
|
||||||
"QQ": "u",
|
|
||||||
"钉钉": "u",
|
|
||||||
"快手": "u",
|
|
||||||
"飞书": "u",
|
|
||||||
"京东": "u"
|
|
||||||
},
|
|
||||||
"快应用": {
|
|
||||||
"华为": "u",
|
|
||||||
"联盟": "u"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,132 @@
|
||||||
|
## 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,372 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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',
|
||||||
|
'font'
|
||||||
|
];
|
||||||
|
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 => {
|
||||||
|
if (style === 'font' && fontSizeReg.test(value)) {
|
||||||
|
const match = fontSizeReg.exec(value);
|
||||||
|
ctx.setFontSize(match[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
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 = 12;
|
||||||
|
if (font) {
|
||||||
|
fontSize = parseInt(font.match(/([\d\.]+)px/)[1])
|
||||||
|
}
|
||||||
|
fontSize /= 2;
|
||||||
|
return {
|
||||||
|
width: strLen(text) * fontSize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_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}) {
|
||||||
|
// echarts.setCanvasCreator(() => canvas);
|
||||||
|
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(){
|
||||||
|
return canvas
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,516 @@
|
||||||
|
<template>
|
||||||
|
<view class="lime-echart" :style="customStyle" v-if="canvasId" ref="limeEchart">
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<canvas
|
||||||
|
class="lime-echart__canvas"
|
||||||
|
v-if="use2dCanvas"
|
||||||
|
type="2d"
|
||||||
|
:id="canvasId"
|
||||||
|
:style="canvasStyle"
|
||||||
|
:disable-scroll="isDisableScroll"
|
||||||
|
@touchstart="touchStart"
|
||||||
|
@touchmove="touchMove"
|
||||||
|
@touchend="touchEnd"
|
||||||
|
/>
|
||||||
|
<canvas
|
||||||
|
class="lime-echart__canvas"
|
||||||
|
v-else-if="isPc"
|
||||||
|
:style="canvasStyle"
|
||||||
|
:id="canvasId"
|
||||||
|
:canvas-id="canvasId"
|
||||||
|
:disable-scroll="isDisableScroll"
|
||||||
|
@mousedown="touchStart"
|
||||||
|
@mousemove="touchMove"
|
||||||
|
@mouseup="touchEnd"
|
||||||
|
/>
|
||||||
|
<canvas
|
||||||
|
class="lime-echart__canvas"
|
||||||
|
v-else
|
||||||
|
:width="nodeWidth"
|
||||||
|
:height="nodeHeight"
|
||||||
|
:style="canvasStyle"
|
||||||
|
:canvas-id="canvasId"
|
||||||
|
:id="canvasId"
|
||||||
|
:disable-scroll="isDisableScroll"
|
||||||
|
@touchstart="touchStart"
|
||||||
|
@touchmove="touchMove"
|
||||||
|
@touchend="touchEnd"
|
||||||
|
/>
|
||||||
|
<canvas v-if="isOffscreenCanvas" :style="offscreenStyle" :canvas-id="offscreenCanvasId"></canvas>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<web-view
|
||||||
|
class="lime-echart__canvas"
|
||||||
|
:id="canvasId"
|
||||||
|
:style="canvasStyle"
|
||||||
|
:webview-styles="webviewStyles"
|
||||||
|
ref="webview"
|
||||||
|
src="/uni_modules/lime-echart/static/index.html"
|
||||||
|
@pagefinish="finished = true"
|
||||||
|
@onPostMessage="onMessage"
|
||||||
|
></web-view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef VUE3
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
global = {}
|
||||||
|
// #endif
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
import {Canvas, setCanvasCreator, dispatch} from './canvas';
|
||||||
|
import { compareVersion, wrapTouch, devicePixelRatio ,sleep} from './utils';
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
import { base64ToPath, sleep } from './utils';
|
||||||
|
// #endif
|
||||||
|
const charts = {}
|
||||||
|
const echartsObj = {}
|
||||||
|
export default {
|
||||||
|
name: 'lime-echart',
|
||||||
|
props: {
|
||||||
|
// #ifdef MP-WEIXIN || MP-TOUTIAO
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: '2d'
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
webviewStyles: Object,
|
||||||
|
// hybrid: Boolean,
|
||||||
|
// #endif
|
||||||
|
customStyle: String,
|
||||||
|
isDisableScroll: Boolean,
|
||||||
|
isClickable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
enableHover: Boolean,
|
||||||
|
beforeDelay: {
|
||||||
|
type: Number,
|
||||||
|
default: 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
|
||||||
|
use2dCanvas: true,
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
|
||||||
|
use2dCanvas: false,
|
||||||
|
// #endif
|
||||||
|
width: null,
|
||||||
|
height: null,
|
||||||
|
nodeWidth: null,
|
||||||
|
nodeHeight: null,
|
||||||
|
canvasNode: null,
|
||||||
|
config: {},
|
||||||
|
inited: false,
|
||||||
|
finished: false,
|
||||||
|
file: '',
|
||||||
|
platform: '',
|
||||||
|
isPc: false,
|
||||||
|
isDown: false,
|
||||||
|
isOffscreenCanvas: false,
|
||||||
|
offscreenWidth: 0,
|
||||||
|
offscreenHeight: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
canvasId() {
|
||||||
|
return `lime-echart${this._ && this._.uid || this._uid}`
|
||||||
|
},
|
||||||
|
offscreenCanvasId() {
|
||||||
|
return `${this.canvasId}_offscreen`
|
||||||
|
},
|
||||||
|
offscreenStyle() {
|
||||||
|
return `width:${this.offscreenWidth}px;height: ${this.offscreenHeight}px; position: fixed; left: 99999px; background: red`
|
||||||
|
},
|
||||||
|
canvasStyle() {
|
||||||
|
return this.width && this.height ? ('width:' + this.width + 'px;height:' + this.height + 'px') : ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.clear()
|
||||||
|
this.dispose()
|
||||||
|
// #ifdef H5
|
||||||
|
if(this.isPc) {
|
||||||
|
document.removeEventListener('mousewheel')
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// #ifdef H5
|
||||||
|
if(!('ontouchstart' in window)) {
|
||||||
|
this.isPc = true
|
||||||
|
document.addEventListener('mousewheel', (e) => {
|
||||||
|
if(this.chart) {
|
||||||
|
const touch = this.getTouch(e)
|
||||||
|
const handler = this.chart.getZr().handler;
|
||||||
|
dispatch.call(handler, 'mousewheel', touch)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY
|
||||||
|
const { SDKVersion, version, platform, environment } = uni.getSystemInfoSync();
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.isPC = /windows/i.test(platform)
|
||||||
|
this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '2.9.2') >= 0 && !((/ios/i.test(platform) && /7.0.20/.test(version)) || /wxwork/i.test(environment)) && !this.isPC;
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
this.isPC = /devtools/i.test(platform)
|
||||||
|
this.use2dCanvas = this.type === '2d' && compareVersion(SDKVersion, '1.78.0') >= 0;
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
this.use2dCanvas = this.type === '2d' && compareVersion(my.SDKVersion, '2.7.0') >= 0;
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$emit('finished')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
onMessage(e) {
|
||||||
|
const res = e?.detail?.data[0] || null;
|
||||||
|
if (res?.event) {
|
||||||
|
if(res.event === 'inited') {
|
||||||
|
this.inited = true
|
||||||
|
}
|
||||||
|
this.$emit(res.event, JSON.parse(res.data));
|
||||||
|
} else if(res?.file){
|
||||||
|
this.file = res.data
|
||||||
|
} else if(!res[0] && JSON.stringify(res[0]) != '{}'){
|
||||||
|
console.error(res);
|
||||||
|
} else {
|
||||||
|
console.log(...res)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
setChart(callback) {
|
||||||
|
if(!this.chart) {
|
||||||
|
console.warn(`组件还未初始化,请先使用 init`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(typeof callback === 'function' && this.chart) {
|
||||||
|
callback(this.chart);
|
||||||
|
}
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
if(typeof callback === 'function') {
|
||||||
|
this.$refs.webview.evalJs(`setChart(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.roptions)})`);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
setOption() {
|
||||||
|
if (!this.chart || !this.chart.setOption) {
|
||||||
|
console.warn(`组件还未初始化,请先使用 init`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.chart.setOption(...arguments);
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
showLoading() {
|
||||||
|
if(this.chart) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.chart.showLoading(...arguments)
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideLoading() {
|
||||||
|
if(this.chart) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.chart.hideLoading()
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`hideLoading()`);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clear() {
|
||||||
|
if(this.chart) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.chart.clear()
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`clear()`);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dispose() {
|
||||||
|
if(this.chart) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.chart.dispose()
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`dispose()`);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resize(size) {
|
||||||
|
if(size && size.width && size.height) {
|
||||||
|
this.height = size.height
|
||||||
|
this.width = size.width
|
||||||
|
if(this.chart) {this.chart.resize(size)}
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`resize(${size})`);
|
||||||
|
// #endif
|
||||||
|
} else {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(this)
|
||||||
|
.select(`.lime-echart`)
|
||||||
|
.boundingClientRect()
|
||||||
|
.exec(res => {
|
||||||
|
if (res) {
|
||||||
|
let { width, height } = res[0];
|
||||||
|
this.width = width = width || 300;
|
||||||
|
this.height = height = height || 300;
|
||||||
|
this.chart.resize({width, height})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$refs.webview.evalJs(`resize()`);
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
canvasToTempFilePath(args = {}) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
const { use2dCanvas, canvasId, canvasNode } = this;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const copyArgs = Object.assign({
|
||||||
|
canvasId,
|
||||||
|
success: resolve,
|
||||||
|
fail: reject
|
||||||
|
}, args);
|
||||||
|
if (use2dCanvas) {
|
||||||
|
delete copyArgs.canvasId;
|
||||||
|
copyArgs.canvas = canvasNode;
|
||||||
|
}
|
||||||
|
uni.canvasToTempFilePath(copyArgs, this);
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.file = ''
|
||||||
|
this.$refs.webview.evalJs(`canvasToTempFilePath()`);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.$watch('file', async (file) => {
|
||||||
|
if(file) {
|
||||||
|
const tempFilePath = await base64ToPath(file)
|
||||||
|
resolve(args.success({tempFilePath}))
|
||||||
|
} else {
|
||||||
|
reject(args.fail({error: ``}))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
async init(echarts, ...args) {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
if(arguments && !arguments.length) {
|
||||||
|
console.error('缺少参数:init(theme?:string, opts?: object, callback: function)')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
if(arguments && arguments.length < 2) {
|
||||||
|
console.error('缺少参数:init(echarts, theme?:string, opts?: object, callback: function)')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
let theme=null,opts={},callback;
|
||||||
|
|
||||||
|
Array.from(arguments).forEach(item => {
|
||||||
|
if(typeof item === 'function') {
|
||||||
|
callback = item
|
||||||
|
}
|
||||||
|
if(['string'].includes(typeof item)) {
|
||||||
|
theme = item
|
||||||
|
}
|
||||||
|
if(typeof item === 'object') {
|
||||||
|
opts = item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(this.beforeDelay) {
|
||||||
|
await sleep(this.beforeDelay)
|
||||||
|
}
|
||||||
|
let config = await this.getContext();
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
if(typeof callback === 'function') {
|
||||||
|
setCanvasCreator(echarts, config)
|
||||||
|
this.chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))
|
||||||
|
callback(this.chart)
|
||||||
|
} else {
|
||||||
|
console.error('callback 非 function')
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
if(callback) {
|
||||||
|
this.chart = {
|
||||||
|
setOption: (options) => {
|
||||||
|
this.roptions = options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(this.chart)
|
||||||
|
this.$refs.webview.evalJs(`init(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.roptions)}, ${JSON.stringify(opts)}, ${theme})`)
|
||||||
|
} else {
|
||||||
|
console.error('callback 非 function')
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
getContext() {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
if(this.finished) {
|
||||||
|
return Promise.resolve(this.finished)
|
||||||
|
}
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.$watch('finished', (val) => {
|
||||||
|
if(val) {
|
||||||
|
resolve(this.finished)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
const { use2dCanvas} = this;
|
||||||
|
let dpr = devicePixelRatio
|
||||||
|
if (use2dCanvas) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(this)
|
||||||
|
.select(`#${this.canvasId}`)
|
||||||
|
.fields({
|
||||||
|
node: true,
|
||||||
|
size: true
|
||||||
|
})
|
||||||
|
.exec(res => {
|
||||||
|
let { node, width, height } = res[0];
|
||||||
|
this.width = width = width || 300;
|
||||||
|
this.height = height = height || 300;
|
||||||
|
const ctx = node.getContext('2d');
|
||||||
|
const canvas = new Canvas(ctx, this, true, node);
|
||||||
|
this.canvasNode = node
|
||||||
|
resolve({ canvas, width, height, devicePixelRatio: dpr, node });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Promise(resolve => {
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(this)
|
||||||
|
.select(`#${this.canvasId}`)
|
||||||
|
.boundingClientRect()
|
||||||
|
.exec(res => {
|
||||||
|
if (res) {
|
||||||
|
let { width, height } = res[0];
|
||||||
|
this.width = width = width || 300;
|
||||||
|
this.height = height = height || 300;
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
dpr = !this.isPC ? devicePixelRatio : 1// 1.25
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-ALIPAY || MP-TOUTIAO
|
||||||
|
dpr = this.isPC ? devicePixelRatio : 1
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-ALIPAY || MP-LARK
|
||||||
|
dpr = devicePixelRatio
|
||||||
|
// #endif
|
||||||
|
this.rect = res[0]
|
||||||
|
this.nodeWidth = width * dpr;
|
||||||
|
this.nodeHeight = height * dpr;
|
||||||
|
const ctx = uni.createCanvasContext(this.canvasId, this);
|
||||||
|
const canvas = new Canvas(ctx, this, false);
|
||||||
|
resolve({ canvas, width, height, devicePixelRatio: dpr });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
getRelative(e) {
|
||||||
|
return {x: e.pageX - this.rect.left, y: e.pageY - this.rect.top, wheelDelta: e.wheelDelta}
|
||||||
|
},
|
||||||
|
getTouch(e) {
|
||||||
|
return e.touches && e.touches[0] && e.touches[0].x ? e.touches[0] : this.getRelative(e);
|
||||||
|
},
|
||||||
|
touchStart(e) {
|
||||||
|
this.isDown = true
|
||||||
|
if (this.chart && ((e.touches.length > 0 || e.touches['0']) && e.type != 'mousemove' || e.type == 'mousedown')) {
|
||||||
|
const touch = this.getTouch(e)
|
||||||
|
this.startX = touch.x
|
||||||
|
this.startY = touch.y
|
||||||
|
this.startT = new Date()
|
||||||
|
const handler = this.chart.getZr().handler;
|
||||||
|
dispatch.call(handler, 'mousedown', touch)
|
||||||
|
dispatch.call(handler, 'mousemove', touch)
|
||||||
|
handler.processGesture(wrapTouch(e), 'start');
|
||||||
|
clearTimeout(this.endTimer);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
touchMove(e) {
|
||||||
|
if(this.isPc && this.enableHover && !this.isDown) {this.isDown = true}
|
||||||
|
if (this.chart && ((e.touches.length > 0 || e.touches['0']) && e.type != 'mousemove' || e.type == 'mousemove' && this.isDown)) {
|
||||||
|
const handler = this.chart.getZr().handler;
|
||||||
|
dispatch.call(handler, 'mousemove', this.getTouch(e))
|
||||||
|
handler.processGesture(wrapTouch(e), 'change');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
touchEnd(e) {
|
||||||
|
this.isDown = false
|
||||||
|
if (this.chart) {
|
||||||
|
const {x} = e.changedTouches && e.changedTouches[0] || {}
|
||||||
|
const touch = (x ? e.changedTouches[0] : this.getRelative(e)) || {};
|
||||||
|
const handler = this.chart.getZr().handler;
|
||||||
|
const isClick = Math.abs(touch.x - this.startX) < 10 && new Date() - this.startT < 200;
|
||||||
|
dispatch.call(handler, 'mouseup', touch)
|
||||||
|
handler.processGesture(wrapTouch(e), 'end');
|
||||||
|
if(isClick) {
|
||||||
|
dispatch.call(handler, 'click', touch)
|
||||||
|
} else {
|
||||||
|
this.endTimer = setTimeout(() => {
|
||||||
|
dispatch.call(handler, 'mousemove', {x: 999999999,y: 999999999});
|
||||||
|
dispatch.call(handler, 'mouseup', {x: 999999999,y: 999999999});
|
||||||
|
},50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.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 */
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,74 @@
|
||||||
|
// #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
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wrapTouch(event) {
|
||||||
|
for (let i = 0; i < event.touches.length; ++i) {
|
||||||
|
const touch = event.touches[i];
|
||||||
|
touch.offsetX = touch.x;
|
||||||
|
touch.offsetY = touch.y;
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
export const devicePixelRatio = wx.getSystemInfoSync().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)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
{
|
||||||
|
"id": "lime-echart",
|
||||||
|
"displayName": "百度图表 echarts",
|
||||||
|
"version": "0.6.5",
|
||||||
|
"description": "echarts 全端兼容,一款使echarts图表能跑在uniapp各端中的插件",
|
||||||
|
"keywords": [
|
||||||
|
"echarts",
|
||||||
|
"canvas",
|
||||||
|
"图表",
|
||||||
|
"可视化"
|
||||||
|
],
|
||||||
|
"repository": "https://gitee.com/liangei/lime-echart",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.6.4"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "",
|
||||||
|
"type": "component-vue"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "u",
|
||||||
|
"IE": "u",
|
||||||
|
"Edge": "u",
|
||||||
|
"Firefox": "u",
|
||||||
|
"Safari": "u"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y",
|
||||||
|
"钉钉": "u",
|
||||||
|
"快手": "u",
|
||||||
|
"飞书": "u",
|
||||||
|
"京东": "u"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "u",
|
||||||
|
"联盟": "u"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,245 @@
|
||||||
|
# echarts 图表 <span style="font-size:16px;">👑👑👑👑👑 <span style="background:#ff9d00;padding:2px 4px;color:#fff;font-size:10px;border-radius: 3px;">全端</span></span>
|
||||||
|
> 一个基于 JavaScript 的开源可视化图表库 [查看更多 站点1](https://limeui.qcoon.cn/#/echart) | [查看更多 站点2](http://liangei.gitee.io/limeui/#/echart) <br>
|
||||||
|
> 基于 echarts 做了兼容处理,更多示例请访问 [uni示例 站点1](https://limeui.qcoon.cn/#/echart-example) | [uni示例 站点2](http://liangei.gitee.io/limeui/#/echart-example) | [官方示例](https://echarts.apache.org/examples/zh/index.html) <br>
|
||||||
|
> Q群:1046793420 <br>
|
||||||
|
|
||||||
|
## 平台兼容
|
||||||
|
|
||||||
|
| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App |
|
||||||
|
| --- | ---------- | ------------ | ---------- | ---------- | --------- | ---- |
|
||||||
|
| √ | √ | √ | √ | √ | √ | √ |
|
||||||
|
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
- 第一步、在uniapp 插件市场 找到 [百度图表](https://ext.dcloud.net.cn/plugin?id=4899) 导入
|
||||||
|
- 第二步、安装 echarts 或者直接使用插件内的echarts.min文件
|
||||||
|
```cmd
|
||||||
|
pnpm add echarts
|
||||||
|
-or-
|
||||||
|
npm install echarts
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
**注意**
|
||||||
|
* 🔔 必须使用hbuilderx 3.4.8-alpha及以上
|
||||||
|
* 🔔 echarts 5.3.0及以上
|
||||||
|
* 🔔 如果是 `cli` 项目需要主动 `import` 插件
|
||||||
|
```js
|
||||||
|
import LEchart from '@/uni_modules/lime-echart/components/l-echart/l-echart.vue';
|
||||||
|
export default {
|
||||||
|
components: {LEchart}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
### 基础用法
|
||||||
|
```html
|
||||||
|
<view><l-echart ref="chart" @finished="init"></l-echart></view>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 如果你使用插件内提供的echarts.min
|
||||||
|
// 也可以自行去官网下载自定义覆盖
|
||||||
|
// 这种方式仅限于vue2
|
||||||
|
import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
|
||||||
|
//---or----------------------------------
|
||||||
|
|
||||||
|
// 如果你使用 npm 安装了 echarts --------- 使用以下方式
|
||||||
|
// 引入全量包
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
//---or----------------------------------
|
||||||
|
|
||||||
|
// 按需引入 开始
|
||||||
|
import * as echarts from 'echarts/core';
|
||||||
|
import {LineChart, BarChart} from 'echarts/charts';
|
||||||
|
import {TitleComponent,TooltipComponent,GridComponent, DatasetComponent, TransformComponent, LegendComponent } from 'echarts/components';
|
||||||
|
// 标签自动布局,全局过渡动画等特性
|
||||||
|
import {LabelLayout,UniversalTransition} from 'echarts/features';
|
||||||
|
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 是必须的一步
|
||||||
|
import {CanvasRenderer} from 'echarts/renderers';
|
||||||
|
|
||||||
|
// 注册必须的组件
|
||||||
|
echarts.use([
|
||||||
|
LegendComponent,
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
LineChart,
|
||||||
|
BarChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
//-------------按需引入结束------------------------
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
option: {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
},
|
||||||
|
confine: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['热度', '正面', '负面']
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
bottom: 15,
|
||||||
|
top: 40,
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
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: {
|
||||||
|
normal: {
|
||||||
|
show: true,
|
||||||
|
position: 'inside'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [300, 270, 340, 344, 300, 320, 310],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '正面',
|
||||||
|
type: 'bar',
|
||||||
|
stack: '总量',
|
||||||
|
label: {
|
||||||
|
normal: {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [120, 102, 141, 174, 190, 250, 220]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '负面',
|
||||||
|
type: 'bar',
|
||||||
|
stack: '总量',
|
||||||
|
label: {
|
||||||
|
normal: {
|
||||||
|
show: true,
|
||||||
|
position: 'left'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [-20, -32, -21, -34, -90, -130, -110]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 组件能被调用必须是组件的节点已经被渲染到页面上
|
||||||
|
// 1、在页面mounted里调用,有时候mounted 组件也未必渲染完成
|
||||||
|
mounted() {
|
||||||
|
// init(echarts, theme?:string, opts?:{}, chart => {})
|
||||||
|
// echarts 必填, 非nvue必填,nvue不用填
|
||||||
|
// theme 可选,应用的主题,目前只支持名称,如:'dark'
|
||||||
|
// opts = { // 可选
|
||||||
|
// locale?: string // 从 `5.0.0` 开始支持
|
||||||
|
// }
|
||||||
|
// chart => {} , callback 必填,返回图表实例
|
||||||
|
this.$refs.chart.init(echarts, chart => {
|
||||||
|
chart.setOption(this.option);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 2、或者使用组件的finished事件里调用
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.$refs.chart.init(echarts, chart => {
|
||||||
|
chart.setOption(this.option);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 数据更新
|
||||||
|
- 使用 `ref` 可获取`setOption`设置更新
|
||||||
|
|
||||||
|
```js
|
||||||
|
this.$refs.chart.setOption(data)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 图表大小
|
||||||
|
- 在有些场景下,我们希望当容器大小改变时,图表的大小也相应地改变。
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 默认获取容器尺寸
|
||||||
|
this.$refs.chart.resize()
|
||||||
|
// 指定尺寸
|
||||||
|
this.$refs.chart.resize({width: 375, height: 375})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
- 微信小程序 `2d` 只支持 真机调试2.0
|
||||||
|
- 微信开发工具会出现canvas不跟随页面的情况,真机不影响
|
||||||
|
- toolbox 不支持 `saveImage`
|
||||||
|
- echarts 5.3.0 的 lines 不支持 trailLength,故需设置为 `0`
|
||||||
|
- dataZoom H5不要设置 `showDetail`
|
||||||
|
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
|
| --------------- | -------- | ------- | ------------ | ----- |
|
||||||
|
| custom-style | 自定义样式 | `string` | - | - |
|
||||||
|
| type | 指定 canvas 类型 | `string` | `2d` | |
|
||||||
|
| is-disable-scroll | 触摸图表时是否禁止页面滚动 | `boolean` | `false` | |
|
||||||
|
| beforeDelay | 延迟初始化 (毫秒) | `number` | `30` | |
|
||||||
|
| enableHover | PC端使用鼠标悬浮 | `boolean` | `false` | |
|
||||||
|
|
||||||
|
## 事件
|
||||||
|
|
||||||
|
| 参数 | 说明 |
|
||||||
|
| --------------- | --------------- |
|
||||||
|
| init(echarts, chart => {}) | 初始化调用函数,第一个参数是传入`echarts`,第二个参数是回调函数,回调函数的参数是 `chart` 实例 |
|
||||||
|
| setChart(chart => {}) | 已经初始化后,请使用这个方法,是个回调函数,参数是 `chart` 实例 |
|
||||||
|
| setOption(data) | [图表配置项](https://echarts.apache.org/zh/option.html#title),用于更新 ,传递是数据 `option` |
|
||||||
|
| clear() | 清空当前实例,会移除实例中所有的组件和图表。 |
|
||||||
|
| dispose() | 销毁实例 |
|
||||||
|
| showLoading() | 显示加载 |
|
||||||
|
| hideLoading() | 隐藏加载 |
|
||||||
|
| [canvasToTempFilePath](https://uniapp.dcloud.io/api/canvas/canvasToTempFilePath.html#canvastotempfilepath)(opt) | 用于生成图片,与官方使用方法一致,但不需要传`canvasId` |
|
||||||
|
|
||||||
|
|
||||||
|
## 打赏
|
||||||
|
如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
|
||||||
|
|
||||||
|

|
||||||
|

|
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,129 @@
|
||||||
|
<!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,
|
||||||
|
.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.3.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(...agrs) {
|
||||||
|
postMessage(agrs)
|
||||||
|
}
|
||||||
|
function emit(event, data) {
|
||||||
|
let dataStr = JSON.stringify(data, stringify)
|
||||||
|
postMessage({
|
||||||
|
event,
|
||||||
|
data: dataStr
|
||||||
|
})
|
||||||
|
cache = []
|
||||||
|
}
|
||||||
|
function postMessage(data) {
|
||||||
|
uni.postMessage({
|
||||||
|
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 = null) {
|
||||||
|
if(!chart) {
|
||||||
|
chart = echarts.init(document.getElementById('limeChart'), theme, opts)
|
||||||
|
if(options) {
|
||||||
|
chart.setOption(options)
|
||||||
|
}
|
||||||
|
// const name = parse('a', callback, options)
|
||||||
|
// console.log('options::', callback)
|
||||||
|
// if(name) this[name] = options
|
||||||
|
// eval(`a = ${callback};`)
|
||||||
|
// if(a) {a(chart)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
const src = chart.getDataURL(opt)
|
||||||
|
postMessage({
|
||||||
|
file: true,
|
||||||
|
data: src
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
var isReady=false;var onReadyCallbacks=[];
|
var isReady=false;var onReadyCallbacks=[];
|
||||||
var isServiceReady=false;var onServiceReadyCallbacks=[];
|
var isServiceReady=false;var onServiceReadyCallbacks=[];
|
||||||
var __uniConfig = {"pages":["pages/index/index","pages/count/count","pages/assess/assess","pages/eliminate/eliminate","pages/contribution/contribution"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"碳足迹计算器","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","titleNView":false,"bounce":"none","scrollIndicator":"none"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"碳中和","compilerVersion":"3.6.18","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
|
var __uniConfig = {"pages":["pages/index/index","pages/count/count","pages/assess/assess","pages/eliminate/eliminate","pages/contribution/contribution"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"碳足迹计算器","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","titleNView":false,"bounce":"none","scrollIndicator":"none"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"碳足迹计算器","compilerVersion":"3.6.18","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}};
|
||||||
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationBarTitleText":"设备判断"}},{"path":"/pages/count/count","meta":{},"window":{"navigationBarTitleText":"计算碳足迹"}},{"path":"/pages/assess/assess","meta":{},"window":{"navigationBarTitleText":"评估碳足迹"}},{"path":"/pages/eliminate/eliminate","meta":{},"window":{"navigationBarTitleText":"消除碳足迹"}},{"path":"/pages/contribution/contribution","meta":{},"window":{"navigationBarTitleText":"在线捐款"}}];
|
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationBarTitleText":"设备判断"}},{"path":"/pages/count/count","meta":{},"window":{"navigationBarTitleText":"计算碳足迹"}},{"path":"/pages/assess/assess","meta":{},"window":{"navigationBarTitleText":"评估碳足迹"}},{"path":"/pages/eliminate/eliminate","meta":{},"window":{"navigationBarTitleText":"消除碳足迹"}},{"path":"/pages/contribution/contribution","meta":{},"window":{"navigationBarTitleText":"在线捐款"}}];
|
||||||
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||||
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__DB95977","name":"碳中和","version":{"name":"1.0.0","code":"100"},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"3.6.18","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}
|
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__DB95977","name":"碳足迹计算器","version":{"name":"1.0.0","code":"100"},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"target":"id:1","autoclose":true,"waiting":true,"delay":0},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"icons":{"android":{"hdpi":"unpackage/res/icons/72x72.png","xhdpi":"unpackage/res/icons/96x96.png","xxhdpi":"unpackage/res/icons/144x144.png","xxxhdpi":"unpackage/res/icons/192x192.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"}}},"google":{"permissions":["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-feature android:name=\"android.hardware.camera\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"]},"apple":{"dSYMs":false},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}}},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"3.6.18","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html"}}
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue