mirror of
https://github.com/ecomfe/vue-echarts.git
synced 2025-11-06 04:46:53 +08:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 977db3d415 | |||
| 0bb1839392 | |||
| 5f57d3fb1c | |||
| 0470d69bba | |||
| 05111f5b6f | |||
| f1ca32d3a4 | |||
| 669ba1cbbb | |||
| ec124f4bf7 | |||
| 9491a904a0 | |||
| d773416b71 | |||
| 20858a6ed0 | |||
| 6304a1b15a | |||
| e44c9dfd40 | |||
| 6d2d3baa5d | |||
| 0e27be6165 | |||
| 0ddc499755 | |||
| 4aaca62b89 | |||
| bbac925b03 | |||
| 49563d3d52 | |||
| 98a2fec975 | |||
| 1d4d0d0302 | |||
| 948d522cf7 | |||
| b11f1efc76 | |||
| 9f5106092b | |||
| 33feda71c0 | |||
| eaceae607d | |||
| 57cd2e6a16 | |||
| e51adb12d0 | |||
| b05f072eb1 | |||
| 259665c4c0 | |||
| 5e51ab1ac6 | |||
| 3256c3d833 | |||
| 2ab85972c9 | |||
| 0dfe4f314a | |||
| 01460d543d | |||
| 899ef4b8d5 | |||
| 677f100b07 | |||
| c1838efb45 | |||
| cdc6ed54d6 | |||
| 89be965939 | |||
| 54ac383b6f | |||
| 7aa9edca96 | |||
| 157a66b75f | |||
| d9722d133b | |||
| bb9540bf4a | |||
| f7f8e4a757 | |||
| 454e9056fa | |||
| 86c22186cc | |||
| a77ecc726d | |||
| 87d9f843ac | |||
| 6e25406cb9 | |||
| dd71918d10 | |||
| c7fd5110f7 | |||
| 9ecb954a9f | |||
| 4d715e5378 | |||
| be2968cc1b | |||
| 23eba11c8f | |||
| 289a0b59dc | |||
| 80710aa0fa | |||
| accab93ea1 | |||
| e10e588d99 | |||
| 14520cb6a5 | |||
| e543866b4d |
22
.eslintrc.js
22
.eslintrc.js
@ -3,18 +3,22 @@ module.exports = {
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/typescript/recommended",
|
||||
"@vue/prettier",
|
||||
"@vue/prettier/@typescript-eslint"
|
||||
],
|
||||
extends: ["plugin:vue/vue3-essential", "eslint:recommended", "@vue/prettier"],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020
|
||||
ecmaVersion: 2020,
|
||||
parser: "@typescript-eslint/parser"
|
||||
},
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
|
||||
}
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.ts"],
|
||||
extends: [
|
||||
"@vue/typescript/recommended",
|
||||
"@vue/prettier/@typescript-eslint"
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
46
.github/ISSUE_TEMPLATE/bug-report.en-US.yml
vendored
Normal file
46
.github/ISSUE_TEMPLATE/bug-report.en-US.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
name: "🐞 Bug Report"
|
||||
description: Create a bug report for Vue-ECharts
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to report this issue!
|
||||
- type: checkboxes
|
||||
id: confirmation
|
||||
attributes:
|
||||
label: Confirmation
|
||||
description: Before submitting this issue, please make sure that the problem only occurs in Vue-ECharts and is not related to ECharts itself.
|
||||
options:
|
||||
- label: I can confirm this problem is not reproducible with ECharts itself.
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: integration
|
||||
attributes:
|
||||
label: How are you introducing Vue-ECharts into your project?
|
||||
options:
|
||||
- ES Module imports
|
||||
- "<script> tag"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: versions
|
||||
attributes:
|
||||
label: Versions
|
||||
description: The output of `npm ls vue echarts vue-echarts`.
|
||||
render: sh
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: Details
|
||||
description: A clear description about the bug.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: repro
|
||||
attributes:
|
||||
label: Reproduction
|
||||
description: "A link to a boiled-down reproduction (a minimal but runnable demo with unnecessary dependencies pruned). If the issue isn't reproducible within an online playground, please create a GitHub repo to reflect the problem. Please paste the link to your CodeSandbox demo or GitHub repo below: ([Vue 3 template](https://codesandbox.io/s/charming-night-2y6m6?file=/src/App.vue) / [Vue 2 template](https://codesandbox.io/s/suspicious-glitter-mk66j?file=/src/App.vue))"
|
||||
validations:
|
||||
required: true
|
||||
46
.github/ISSUE_TEMPLATE/bug-report.zh-Hans.yml
vendored
Normal file
46
.github/ISSUE_TEMPLATE/bug-report.zh-Hans.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
name: "🐞 Bug 报告"
|
||||
description: 给 Vue-ECharts 报告 bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您花时间报告这个问题!
|
||||
- type: checkboxes
|
||||
id: confirmation
|
||||
attributes:
|
||||
label: 请确认
|
||||
description: 在提交此问题前,请确认问题仅在 Vue-ECharts 中发生,而与 ECharts 本身无关。
|
||||
options:
|
||||
- label: 我可以确认这个问题无法在 ECharts 项目本身中复现。
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: integration
|
||||
attributes:
|
||||
label: 您是如何将 Vue-ECharts 引入项目的?
|
||||
options:
|
||||
- 通过 ES 模块 import
|
||||
- "<script> 标签"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: versions
|
||||
attributes:
|
||||
label: 版本信息
|
||||
description: 在命令行执行 `npm ls vue echarts vue-echarts` 的输出。
|
||||
render: sh
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: 问题详情
|
||||
description: 请清晰地描述您遇到的问题。
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: repro
|
||||
attributes:
|
||||
label: 问题复现
|
||||
description: "请提供一个精炼的问题复现(去除无关依赖的最小化可运行 demo)。如果在线环境无法复现,可以创建对应的 GitHub repo 来提供复现环境。请在下方贴入在 CodeSandbox 上 demo 的链接或 GitHub repo 链接:([Vue 3 模板](https://codesandbox.io/s/charming-night-2y6m6?file=/src/App.vue) / [Vue 2 模板](https://codesandbox.io/s/suspicious-glitter-mk66j?file=/src/App.vue))"
|
||||
validations:
|
||||
required: true
|
||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
22
.github/ISSUE_TEMPLATE/feature-request.en-US.yml
vendored
Normal file
22
.github/ISSUE_TEMPLATE/feature-request.en-US.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: "✨ Feature Request"
|
||||
description: Create a feature request for Vue-ECharts
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to report this issue!
|
||||
- type: checkboxes
|
||||
id: confirmation
|
||||
attributes:
|
||||
label: Confirmation
|
||||
description: Before submitting the issue, please make sure you did the following check.
|
||||
options:
|
||||
- label: I can confirm this is a feature request for the Vue component instead of ECharts itself.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: Details
|
||||
description: A clear description about the use case of the new feature and its potential API.
|
||||
validations:
|
||||
required: true
|
||||
22
.github/ISSUE_TEMPLATE/feature-request.zh-Hans.yml
vendored
Normal file
22
.github/ISSUE_TEMPLATE/feature-request.zh-Hans.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: "✨ 新功能建议"
|
||||
description: 给 Vue-ECharts 提交新功能建议
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您花时间报告这个问题!
|
||||
- type: checkboxes
|
||||
id: confirmation
|
||||
attributes:
|
||||
label: 提前确认
|
||||
description: 在提交此建议前,请确认下述情况。
|
||||
options:
|
||||
- label: 我可以确认这个新功能建议是提交给此 Vue 组件的,而不应该提交到 ECharts 项目本身。
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: 新功能详情
|
||||
description: 请清晰地描述此功能的适用场景,以及可能的相关 API 的设想。
|
||||
validations:
|
||||
required: true
|
||||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"trailingComma": "none",
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
82
CHANGELOG.md
82
CHANGELOG.md
@ -1,3 +1,85 @@
|
||||
## 6.3.3
|
||||
|
||||
* Make autoresize work for grid layout by default (#675).
|
||||
|
||||
## 6.3.2
|
||||
|
||||
* Added basic types for events (only event names).
|
||||
|
||||
## 6.3.1
|
||||
|
||||
* Revert the style change to prevent tooltips from being clipped.
|
||||
|
||||
## 6.3.0
|
||||
|
||||
* Injected values can now be wrapped in an object so that they can be reactive in Vue 2.
|
||||
|
||||
## 6.2.4
|
||||
|
||||
* Fixed that attributes were not outputted onto the chart root element for Vue 2 (#670).
|
||||
|
||||
## 6.2.3
|
||||
|
||||
* Fixed the problem that `v-on` stops working after upgrading to `vue@2.7.x`.
|
||||
|
||||
## 6.2.2
|
||||
|
||||
* Improve types for `update-options`.
|
||||
|
||||
## 6.2.1
|
||||
|
||||
* Improved types for provide/inject API.
|
||||
|
||||
## 6.2.0
|
||||
|
||||
* Added support for Vue 2.7+.
|
||||
|
||||
## 6.1.0
|
||||
|
||||
* Added support for `.once` event modifier.
|
||||
|
||||
## 6.0.3
|
||||
|
||||
* Improved typings for Vue 2 version.
|
||||
|
||||
## 6.0.2
|
||||
|
||||
* Make `notMerge` option still respect `update-options`.
|
||||
* The default behavior of `notMerge` now revert to checking if there is a reference change for the `option` prop.
|
||||
|
||||
## 6.0.1
|
||||
|
||||
* Update should always be `notMerge: true`.
|
||||
* Update dependency version for vue-demi.
|
||||
|
||||
## 6.0.0
|
||||
|
||||
* Update dependency versions.
|
||||
|
||||
## 6.0.0-rc.6
|
||||
|
||||
* Revert the change of `updateOptions.lazyUpdate`. It defaults to `false` again.
|
||||
* Fixed the occasional error caused by the internal implementation of ECharts.
|
||||
* Removed unexpected `console.log` call.
|
||||
|
||||
## 6.0.0-rc.5
|
||||
|
||||
* Changed `updateOptions.lazyUpdate` to `true` by default. ([#533](https://github.com/ecomfe/vue-echarts/issues/533#issuecomment-809883909))
|
||||
* Only perform an additional `resize` call after init within a task. ([#533](https://github.com/ecomfe/vue-echarts/issues/533#issuecomment-809883909))
|
||||
* The `.chart` getter API now works for Vue 2. (#542)
|
||||
|
||||
## 6.0.0-rc.4
|
||||
|
||||
* Fix type error for `Vue2` reference.
|
||||
|
||||
## 6.0.0-rc.3
|
||||
|
||||
* Add missing types file for Vue 2.
|
||||
|
||||
## 6.0.0-rc.2
|
||||
|
||||
* Fix postinstall script.
|
||||
|
||||
## 6.0.0-rc.1
|
||||
|
||||
* Move inital resize timing earlier into microtasks so that minimize visual layout shift.
|
||||
|
||||
257
README.md
257
README.md
@ -4,7 +4,7 @@
|
||||
|
||||
> [🇨🇳 中文版](./README.zh-Hans.md)
|
||||
|
||||
Uses [Apache ECharts](http://echarts.baidu.com/index.html) 5 and works for both [Vue.js](https://vuejs.org/) 2/3.
|
||||
Uses [Apache ECharts](https://echarts.apache.org/en/index.html) 5 and works for both [Vue.js](https://vuejs.org/) 2/3.
|
||||
|
||||
## 💡 Heads up 💡
|
||||
|
||||
@ -20,87 +20,31 @@ Not ready yet? Read documentation for older versions [here →](https://github.c
|
||||
$ npm install echarts vue-echarts
|
||||
```
|
||||
|
||||
To make `vue-echarts` work for Vue 2, you need to have `@vue/composition-api` installed:
|
||||
To make `vue-echarts` work for _Vue 2_ (<2.7.0), you need to have `@vue/composition-api` installed:
|
||||
|
||||
```sh
|
||||
npm i -D @vue/composition-api
|
||||
```
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
If you are using _NuxtJS_ on top of _Vue 2_ (<2.7.0), you'll also need `@nuxtjs/composition-api`:
|
||||
|
||||
```js
|
||||
import { createApp } from 'vue'
|
||||
import ECharts from 'vue-echarts'
|
||||
|
||||
// import ECharts modules manually to reduce bundle size
|
||||
import {
|
||||
CanvasRenderer
|
||||
} from 'echarts/renderers'
|
||||
import {
|
||||
BarChart
|
||||
} from 'echarts/charts'
|
||||
import {
|
||||
GridComponent,
|
||||
TooltipComponent
|
||||
} from 'echarts/components'
|
||||
|
||||
const app = createApp(...)
|
||||
|
||||
// register globally (or you can do it locally)
|
||||
app.component('v-chart', ECharts)
|
||||
|
||||
app.mount(...)
|
||||
```sh
|
||||
npm i -D @nuxtjs/composition-api
|
||||
```
|
||||
|
||||
</details>
|
||||
And then add `'@nuxtjs/composition-api/module'` in the `buildModules` option in your `nuxt.config.js`.
|
||||
|
||||
#### Example
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import ECharts from 'vue-echarts'
|
||||
|
||||
// import ECharts modules manually to reduce bundle size
|
||||
import {
|
||||
CanvasRenderer
|
||||
} from 'echarts/renderers'
|
||||
import {
|
||||
BarChart
|
||||
} from 'echarts/charts'
|
||||
import {
|
||||
GridComponent,
|
||||
TooltipComponent
|
||||
} from 'echarts/components'
|
||||
|
||||
// register globally (or you can do it locally)
|
||||
Vue.component('v-chart', ECharts)
|
||||
|
||||
new Vue(...)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
We encourage manually importing components and charts from ECharts for smaller bundle size. See all supported renderers/charts/components [here →](https://github.com/apache/echarts/blob/master/src/echarts.all.ts)
|
||||
|
||||
But if you really want to import the whole ECharts bundle without having to import modules manually, just add this in your code:
|
||||
|
||||
```js
|
||||
import "echarts";
|
||||
```
|
||||
|
||||
#### SFC example
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
<summary>Vue 3 <a href="https://stackblitz.com/edit/vue-echarts-vue-3?file=src%2FApp.vue">Demo →</a></summary>
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<v-chart class="chart" :option="option" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { use } from "echarts/core";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { PieChart } from "echarts/charts";
|
||||
@ -110,7 +54,7 @@ import {
|
||||
LegendComponent
|
||||
} from "echarts/components";
|
||||
import VChart, { THEME_KEY } from "vue-echarts";
|
||||
import { ref, defineComponent } from "vue";
|
||||
import { ref, provide } from "vue";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
@ -120,55 +64,44 @@ use([
|
||||
LegendComponent
|
||||
]);
|
||||
|
||||
export default defineComponent({
|
||||
name: "HelloWorld",
|
||||
components: {
|
||||
VChart
|
||||
},
|
||||
provide: {
|
||||
[THEME_KEY]: "dark"
|
||||
},
|
||||
setup: () => {
|
||||
const option = ref({
|
||||
title: {
|
||||
text: "Traffic Sources",
|
||||
left: "center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
left: "left",
|
||||
data: ["Direct", "Email", "Ad Networks", "Video Ads", "Search Engines"]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Traffic Sources",
|
||||
type: "pie",
|
||||
radius: "55%",
|
||||
center: ["50%", "60%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" }
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
provide(THEME_KEY, "dark");
|
||||
|
||||
return { option };
|
||||
}
|
||||
const option = ref({
|
||||
title: {
|
||||
text: "Traffic Sources",
|
||||
left: "center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
left: "left",
|
||||
data: ["Direct", "Email", "Ad Networks", "Video Ads", "Search Engines"]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Traffic Sources",
|
||||
type: "pie",
|
||||
radius: "55%",
|
||||
center: ["50%", "60%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" }
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -179,12 +112,10 @@ export default defineComponent({
|
||||
</style>
|
||||
```
|
||||
|
||||
[Demo →](https://codesandbox.io/s/charming-night-2y6m6?file=/src/App.vue)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
<summary>Vue 2 <a href="https://stackblitz.com/edit/vue-echarts-vue-2?file=src%2FApp.vue">Demo →</a></summary>
|
||||
|
||||
```vue
|
||||
<template>
|
||||
@ -275,22 +206,28 @@ export default {
|
||||
</style>
|
||||
```
|
||||
|
||||
[Demo →](https://codesandbox.io/s/suspicious-glitter-mk66j?file=/src/App.vue)
|
||||
|
||||
</details>
|
||||
|
||||
We encourage manually importing components and charts from ECharts for smaller bundle size. See all supported renderers/charts/components [here →](https://github.com/apache/echarts/blob/master/src/echarts.all.ts)
|
||||
|
||||
But if you really want to import the whole ECharts bundle without having to import modules manually, just add this in your code:
|
||||
|
||||
```js
|
||||
import "echarts";
|
||||
```
|
||||
|
||||
### CDN & Global variable
|
||||
|
||||
Drop `<script>` inside your HTML file and access the component via `window.VueECharts`.
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
<details>
|
||||
<summary>Vue 3 <a href="https://stackblitz.com/edit/vue-echarts-vue-3-global?file=index.html">Demo →</a></summary>
|
||||
|
||||
<!-- vue3Scripts:start -->
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@3.0.7"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.0.2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.0.0-rc.1"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.37"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.3.2"></script>
|
||||
```
|
||||
<!-- vue3Scripts:end -->
|
||||
|
||||
@ -301,23 +238,16 @@ const app = Vue.createApp(...)
|
||||
app.component('v-chart', VueECharts)
|
||||
```
|
||||
|
||||
<!-- vue3Demo:start -->
|
||||
|
||||
[Demo →](https://codesandbox.io/api/v1/sandboxes/define?parameters=N4IgZglgNgpgziAXKCA7AJjAHgOgBYAuAtlEqAMYD2qBMNSIAPAIQAiA8gMIAqAmgAoBRAASESAPgA6qRmKhSZeGAEN0CxnAIBPWAoDEygA6HhwacNEwIAc0KJhAFgAMTw1gDc0gL7TGAek0dGHU_JVV1ACNKdC11dAgAN2EIdABeSRAjQwyFC0YEgFpyPGUAJwJhZQBXAkpS-AgALxhhREpDAghqdJB2zuoMvxD4hPU4clKIDuE4UvIewgJDOEQ_P3J0VBwAKzhMKETSnFQYAj9UQyI_BKqYAAEAZhwnHAB2HP9xyY6xiamK2bzDKLZardabHZ7GAHBJHE5nC5XGDFMoEOB3ACszxwACYPgE_j9fF9_jM5gsCEsVmsNltdvtDsdTudLtdbgVkSVyuiAGzYpwFOY4ACM-JJRJk4oICgAarccBMVLQAILGAAUZlQFnQygIyjVAEpTOYLMJ6gQqqUtZrTaa-l1UPYbbbTbQsAQAMraWBOk0u01gagEABiyiI0C09gA5ABJGgwUoAGmEGQAEtCEqcIORlMIAHIwW4ZZPKybKKDJuDKVBwApwBMQMBRv0uryJlu2zoEH3GrX-13YAj2DLcUrKMCQcjCD2US3keDFjsu2BgIcpkDz-OlDJLixt3fCWqUKCdQy-vv9w-TazWBPDkAQWhERcX_uB0pEXW0Ur34DKLzCIwESlEMwARABTrkABGroF4ACkBo7q-tr7shpqwLeGDnpeFh1BAdBrhkmblNm5YvjhwgroRIBUeROE6nq9gANoHraGSsBA9TkAQdEURkgiftAvE4RkyroPmpwAO51AA1nAwmXhkMopDAlDCGJ8kgO2aH-hkHoqHMeDCIIqDWGgC4gKxwgALoHqhl71pM8DMVZzoUagYYwPeo7jpO06znMFnaRRFjaIYXnroY-EKf2Y7xFUKzrhiGJwTF_qbt-LkgBiTipVp648rlGTWcFIUMcoLk6f2wDCAk5a3PYDwPBiyYeUQEXsZxyI8SAwj2SFFg1XVUANcIDzCk4rWefeAnKEJvX9QNQ31RFOIPA4U3tfeYkSQQ0mlHJGR9aVS21St9jCs1m0dSAymYGpGlHYtIXLSNEXChiDgABzXfe-llMUxmmeZml9VZFgleDwgwEQhglHAECJW5IWPjDXpBNhA2mnAJToJQkkAEIjT-wgTSdWM46o-PsBO9YEAAGvYk1Q7alN45JnDHnU96lNYET6pNwiC8LOAYohllVf6PiS6a0sUXL_a2WhCt7p4fbS14iF9gqlCw9QBFqkRRRcj1yZyjAgicCbcBaxYOBELONCGyABjGBkBpq58hLSr4fhRDEIRyOIIBeKHQA)
|
||||
|
||||
<!-- vue3Demo:end -->
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
<summary>Vue 2 <a href="https://stackblitz.com/edit/vue-echarts-vue-2-global?file=index.html">Demo →</a></summary>
|
||||
|
||||
<!-- vue2Scripts:start -->
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.0.0-rc.3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.0.2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.0.0-rc.1"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.5"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.3.2"></script>
|
||||
```
|
||||
<!-- vue2Scripts:end -->
|
||||
|
||||
@ -326,12 +256,6 @@ app.component('v-chart', VueECharts)
|
||||
Vue.component("v-chart", VueECharts);
|
||||
```
|
||||
|
||||
<!-- vue2Demo:start -->
|
||||
|
||||
[Demo →](https://codesandbox.io/api/v1/sandboxes/define?parameters=N4IgZglgNgpgziAXKCA7AJjAHgOgBYAuAtlEqAMYD2qBMNSIAPAIQAiA8gMIAqAmgAoBRAASESAPgA6qRmKhSZeGAEN0CxnAIBPWAoDEygA6HhwacNEwIAc0KJhAFgAMTw1gDc0gL7TGAek0dGHU_JVV1ACNKdC11dAgAN2EIdABeSRAjQwyFC0YEgFpyPGUAJwJhZQBXAkpS-AgALxhhREpDAghqdJB2zuoMvxD4hPU4clKIDuE4UvIewgJDOEQ_P3J0VBwAKzhMKETSnFQYAj9UQyI_BKqYAAEAJhwANhwARgec_3HJjrGJqYVWbzDKLZardabHZ7GAHBJHE5nC5XO43GDrShEQyUOAQfqoApGCB3N44JxkgpzHAAZi-AQBf18P0BMzmCwISxWaw2W12-0Ox1O50ufhgxTKBDgdwArGScJ8QOJvgyCP9fkC2aCOeDuVC-bCBYjhVc0QUxSVylLXuSnJTyO86czGTInarpAA1W44KhY6h0AgACgyhXF5QyABphJ6YIJOBbJQBKTyoaQnADuUduAbMqAssPsGQMxgj5mE6GUBGUAYTplLFnqBCqpVzOYsbeEfS6qHsrfbbdoWAIAGVtLAe3W-xYwNQCAAxZREaBaewAcgAkjQYKVIxkABKwhKnCDkZTCAByMFuEeEAEFJsooJG4MpUHACnAtxAwCuJ-2vOHf37PEx1rXNJ37bACALEBuFKZQwEgchhCHSgm3IeASzA8DhFgMAoOEDJ0M3UoMkAix_zI4RakoKBOkMccsPAghJmsawt2gvEYCITDsKnOoiArWhSmg4BlC8YRGAiUohmACJxJ7chxOzdAvAAUgTUjGL_ACtLbWA2IwBjeI7SZ_Wgw9ymPB8eN43D8IyOybOw8tK3sABtSj2wyVgIHqcgCCc3iMkEAToEC7CMhvdBz1ONM6gAazgcLwIyd0UhgShb3QJKQB04yLAyIcVDmPBhEEVBrDQDCQE84QAF1KIo3SLA_UyVmEDzmrbXtjNQBcYGg2D4MQ5DULmaq8vy7RDAGgiQEMCAYGSyc4PiKp2oyaVpVU5a-yIoT3M2pwdtyubnmOjI6sm4yXOUQ6usnYBhASB9bnsalqWlSM-qIWbvN8sUApAYQmvy7rnte2bqTeJxvv66CQuUMLgdBsHTAhqA3uEB5qQcOHfugqKYoIOLSkSjIQeu_KnpezHZreT78b-kA0swTKopyynavbGnIfsN5pQcAAOJnoKKspijKiqqs5nwHrbK7ueELjDBKXF2p6_LOKIEcgiMtGWpKdBKDTAAhTHhOEGGqbBuAjZN9gEI_AgAA17FhpX2zt1QTc4Gi6mg0prAiKtYeEMOI5waUNJq-W_yVuXjMT8CGt05PyOTcjvCTXx6XVEIohiEI5HEEAvHLoA)
|
||||
|
||||
<!-- vue2Demo:end -->
|
||||
|
||||
</details>
|
||||
|
||||
See more examples [here](https://github.com/ecomfe/vue-echarts/tree/main/src/demo).
|
||||
@ -354,6 +278,8 @@ See more examples [here](https://github.com/ecomfe/vue-echarts/tree/main/src/dem
|
||||
|
||||
ECharts' universal interface. Modifying this prop will trigger ECharts' `setOption` method. Read more [here →](https://echarts.apache.org/en/option.html)
|
||||
|
||||
> 💡 When `update-options` is not specified, `notMerge: false` will be specified by default when the `setOption` method is called if the `option` object is modified directly and the reference remains unchanged; otherwise, if a new reference is bound to `option`, ` notMerge: true` will be specified.
|
||||
|
||||
- `update-options: object`
|
||||
|
||||
Options for updating chart option. See `echartsInstance.setOption`'s `opts` parameter [here →](https://echarts.apache.org/en/api.html#echartsInstance.setOption)
|
||||
@ -386,20 +312,20 @@ See more examples [here](https://github.com/ecomfe/vue-echarts/tree/main/src/dem
|
||||
|
||||
Vue-ECharts provides provide/inject API for `theme`, `init-options`, `update-options` and `loading-options` to help configuring contextual options. eg. for `init-options` you can use the provide API like this:
|
||||
|
||||
<details open>
|
||||
<details>
|
||||
<summary>Vue 3</summary>
|
||||
|
||||
```js
|
||||
import { INIT_OPTIONS_KEY } from 'vue-echarts'
|
||||
import { THEME_KEY } from 'vue-echarts'
|
||||
import { provide } from 'vue'
|
||||
|
||||
// composition API
|
||||
provide(INIT_OPTIONS_KEY, ...)
|
||||
provide(THEME_KEY, 'dark')
|
||||
|
||||
// options API
|
||||
{
|
||||
provide: {
|
||||
[INIT_OPTIONS_KEY]: { ... }
|
||||
[THEME_KEY]: 'dark'
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -410,16 +336,36 @@ provide(INIT_OPTIONS_KEY, ...)
|
||||
<summary>Vue 2</summary>
|
||||
|
||||
```js
|
||||
import { INIT_OPTIONS_KEY } from 'vue-echarts'
|
||||
import { THEME_KEY } from 'vue-echarts'
|
||||
|
||||
// in component options
|
||||
{
|
||||
provide: {
|
||||
[INIT_OPTIONS_KEY]: { ... }
|
||||
[THEME_KEY]: 'dark'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> You need to provide an object for Vue 2 if you want to change it dynamically.
|
||||
>
|
||||
> ```js
|
||||
> // in component options
|
||||
> {
|
||||
> data () {
|
||||
> return {
|
||||
> theme: { value: 'dark' }
|
||||
> }
|
||||
> },
|
||||
> provide () {
|
||||
> return {
|
||||
> [THEME_KEY]: this.theme
|
||||
> }
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
|
||||
</details>
|
||||
|
||||
### Methods
|
||||
@ -436,7 +382,6 @@ import { INIT_OPTIONS_KEY } from 'vue-echarts'
|
||||
- `containPixel` [→](https://echarts.apache.org/en/api.html#echartsInstance.containPixel)
|
||||
- `showLoading` [→](https://echarts.apache.org/en/api.html#echartsInstance.showLoading)
|
||||
- `hideLoading` [→](https://echarts.apache.org/en/api.html#echartsInstance.hideLoading)
|
||||
- `containPixel` [→](https://echarts.apache.org/en/api.html#echartsInstance.containPixel)
|
||||
- `getDataURL` [→](https://echarts.apache.org/en/api.html#echartsInstance.getDataURL)
|
||||
- `getConnectedDataURL` [→](https://echarts.apache.org/en/api.html#echartsInstance.getConnectedDataURL)
|
||||
- `clear` [→](https://echarts.apache.org/en/api.html#echartsInstance.clear)
|
||||
@ -448,6 +393,18 @@ Static methods can be accessed from [`echarts` itself](https://echarts.apache.or
|
||||
|
||||
### Events
|
||||
|
||||
You can bind events with Vue's `v-on` directive.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<v-chart :option="option" @highlight="handleHighlight" />
|
||||
</template>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Only the `.once` event modifier is supported as other modifiers are tightly coupled with the DOM event system.
|
||||
|
||||
Vue-ECharts support the following events:
|
||||
|
||||
- `highlight` [→](https://echarts.apache.org/en/api.html#events.highlight)
|
||||
@ -504,7 +461,7 @@ The following breaking changes are introduced in `vue-echarts@6`:
|
||||
|
||||
### Vue 2 support
|
||||
|
||||
- Now `@vue/composition-api` is required to be installed to use Vue-ECharts with Vue 2.
|
||||
- If you are using version prior to `vue@2.7.0`, `@vue/composition-api` is required to be installed to use Vue-ECharts with Vue 2.
|
||||
|
||||
### Props
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
> Apache ECharts 的 Vue.js 组件。
|
||||
|
||||
使用 [Apache ECharts](http://echarts.baidu.com/index.html) 5,同时支持 [Vue.js](https://vuejs.org/) 2/3。
|
||||
使用 [Apache ECharts](https://echarts.apache.org/zh/index.html) 5,同时支持 [Vue.js](https://vuejs.org/) 2/3。
|
||||
|
||||
## 💡 注意 💡
|
||||
|
||||
@ -18,87 +18,31 @@
|
||||
$ npm install echarts vue-echarts
|
||||
```
|
||||
|
||||
要在 Vue 2 下使用 `vue-echarts`,需要确保 `@vue/composition-api` 已经安装:
|
||||
要在 _Vue 2_(<2.7.0)下使用 `vue-echarts`,需要确保 `@vue/composition-api` 已经安装:
|
||||
|
||||
```sh
|
||||
npm i -D @vue/composition-api
|
||||
```
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
如果你在使用基于 _Vue 2_(<2.7.0)的 _NuxtJS_,那么还需要安装 `@nuxtjs/composition-api`:
|
||||
|
||||
```js
|
||||
import { createApp } from 'vue'
|
||||
import ECharts from 'vue-echarts'
|
||||
|
||||
// 手动引入 ECharts 各模块来减小打包体积
|
||||
import {
|
||||
CanvasRenderer
|
||||
} from 'echarts/renderers'
|
||||
import {
|
||||
BarChart
|
||||
} from 'echarts/charts'
|
||||
import {
|
||||
GridComponent,
|
||||
TooltipComponent
|
||||
} from 'echarts/components'
|
||||
|
||||
const app = createApp(...)
|
||||
|
||||
// 全局注册组件(也可以使用局部注册)
|
||||
app.component('v-chart', ECharts)
|
||||
|
||||
app.mount(...)
|
||||
```sh
|
||||
npm i -D @nuxtjs/composition-api
|
||||
```
|
||||
|
||||
</details>
|
||||
然后在 `nuxt.config.js` 的 `buildModules` 选项中添加 `'@nuxtjs/composition-api/module'`。
|
||||
|
||||
#### 示例
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import ECharts from 'vue-echarts'
|
||||
|
||||
// 手动引入 ECharts 各模块来减小打包体积
|
||||
import {
|
||||
CanvasRenderer
|
||||
} from 'echarts/renderers'
|
||||
import {
|
||||
BarChart
|
||||
} from 'echarts/charts'
|
||||
import {
|
||||
GridComponent,
|
||||
TooltipComponent
|
||||
} from 'echarts/components'
|
||||
|
||||
// 全局注册组件(也可以使用局部注册)
|
||||
Vue.component('v-chart', ECharts)
|
||||
|
||||
new Vue(...)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
为了更小的打包体积,我们建议手动从 ECharts 引入单个图表和组件。请参考所有支持的渲染器/图表/组件。[前往 →](https://github.com/apache/echarts/blob/master/src/echarts.all.ts)
|
||||
|
||||
但如果你实在需要全量引入 ECharts 从而无需手动引入模块,只需要在代码中添加:
|
||||
|
||||
```js
|
||||
import "echarts";
|
||||
```
|
||||
|
||||
#### 单文件组件示例
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
<summary>Vue 3 <a href="https://stackblitz.com/edit/vue-echarts-vue-3?file=src%2FApp.vue">Demo →</a></summary>
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<v-chart class="chart" :option="option" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { use } from "echarts/core";
|
||||
import { CanvasRenderer } from "echarts/renderers";
|
||||
import { PieChart } from "echarts/charts";
|
||||
@ -108,7 +52,7 @@ import {
|
||||
LegendComponent
|
||||
} from "echarts/components";
|
||||
import VChart, { THEME_KEY } from "vue-echarts";
|
||||
import { ref, defineComponent } from "vue";
|
||||
import { ref, provide } from "vue";
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
@ -118,55 +62,44 @@ use([
|
||||
LegendComponent
|
||||
]);
|
||||
|
||||
export default defineComponent({
|
||||
name: "HelloWorld",
|
||||
components: {
|
||||
VChart
|
||||
},
|
||||
provide: {
|
||||
[THEME_KEY]: "dark"
|
||||
},
|
||||
setup: () => {
|
||||
const option = ref({
|
||||
title: {
|
||||
text: "Traffic Sources",
|
||||
left: "center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
left: "left",
|
||||
data: ["Direct", "Email", "Ad Networks", "Video Ads", "Search Engines"]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Traffic Sources",
|
||||
type: "pie",
|
||||
radius: "55%",
|
||||
center: ["50%", "60%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" }
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
provide(THEME_KEY, "dark");
|
||||
|
||||
return { option };
|
||||
}
|
||||
const option = ref({
|
||||
title: {
|
||||
text: "Traffic Sources",
|
||||
left: "center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
left: "left",
|
||||
data: ["Direct", "Email", "Ad Networks", "Video Ads", "Search Engines"]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Traffic Sources",
|
||||
type: "pie",
|
||||
radius: "55%",
|
||||
center: ["50%", "60%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" }
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -180,7 +113,7 @@ export default defineComponent({
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
<summary>Vue 2 <a href="https://stackblitz.com/edit/vue-echarts-vue-2?file=src%2FApp.vue">Demo →</a></summary>
|
||||
|
||||
```vue
|
||||
<template>
|
||||
@ -273,18 +206,26 @@ export default {
|
||||
|
||||
</details>
|
||||
|
||||
为了更小的打包体积,我们建议手动从 ECharts 引入单个图表和组件。请参考所有支持的渲染器/图表/组件。[前往 →](https://github.com/apache/echarts/blob/master/src/echarts.all.ts)
|
||||
|
||||
但如果你实在需要全量引入 ECharts 从而无需手动引入模块,只需要在代码中添加:
|
||||
|
||||
```js
|
||||
import "echarts";
|
||||
```
|
||||
|
||||
### CDN & 全局变量
|
||||
|
||||
用如下方式在 HTML 中插入 `<script>` 标签,并且通过 `window.VueECharts` 来访问组件接口:
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
<details>
|
||||
<summary>Vue 3 <a href="https://stackblitz.com/edit/vue-echarts-vue-3-global?file=index.html">Demo →</a></summary>
|
||||
|
||||
<!-- vue3Scripts:start -->
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@3.0.7"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.0.2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.0.0-rc.1"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.37"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.3.2"></script>
|
||||
```
|
||||
<!-- vue3Scripts:end -->
|
||||
|
||||
@ -295,23 +236,16 @@ const app = Vue.createApp(...)
|
||||
app.component('v-chart', VueECharts)
|
||||
```
|
||||
|
||||
<!-- vue3Demo:start -->
|
||||
|
||||
[Demo →](https://codesandbox.io/api/v1/sandboxes/define?parameters=N4IgZglgNgpgziAXKCA7AJjAHgOgBYAuAtlEqAMYD2qBMNSIAPAIQAiA8gMIAqAmgAoBRAASESAPgA6qRmKhSZeGAEN0CxnAIBPWAoDEygA6HhwacNEwIAc0KJhAFgAMTw1gDc0gL7TGAek0dGHU_JVV1ACNKdC11dAgAN2EIdABeSRAjQwyFC0YEgFpyPGUAJwJhZQBXAkpS-AgALxhhREpDAghqdJB2zuoMvxD4hPU4clKIDuE4UvIewgJDOEQ_P3J0VBwAKzhMKETSnFQYAj9UQyI_BKqYAAEAZhwnHAB2HP9xyY6xiamK2bzDKLZardabHZ7GAHBJHE5nC5XGDFMoEOB3ACszxwACYPgE_j9fF9_jM5gsCEsVmsNltdvtDsdTudLtdbgVkSVyuiAGzYpwFOY4ACM-JJRJk4oICgAarccBMVLQAILGAAUZlQFnQygIyjVAEpTOYLMJ6gQqqUtZrTaa-l1UPYbbbTbQsAQAMraWBOk0u01gagEABiyiI0C09gA5ABJGgwUoAGmEGQAEtCEqcIORlMIAHIwW4ZZPKybKKDJuDKVBwApwBMQMBRv0uryJlu2zoEH3GrX-13YAj2DLcUrKMCQcjCD2US3keDFjsu2BgIcpkDz-OlDJLixt3fCWqUKCdQy-vv9w-TazWBPDkAQWhERcX_uB0pEXW0Ur34DKLzCIwESlEMwARABTrkABGroF4ACkBo7q-tr7shpqwLeGDnpeFh1BAdBrhkmblNm5YvjhwgroRIBUeROE6nq9gANoHraGSsBA9TkAQdEURkgiftAvE4RkyroPmpwAO51AA1nAwmXhkMopDAlDCGJ8kgO2aH-hkHoqHMeDCIIqDWGgC4gKxwgALoHqhl71pM8DMVZzoUagYYwPeo7jpO06znMFnaRRFjaIYXnroY-EKf2Y7xFUKzrhiGJwTF_qbt-LkgBiTipVp648rlGTWcFIUMcoLk6f2wDCAk5a3PYDwPBiyYeUQEXsZxyI8SAwj2SFFg1XVUANcIDzCk4rWefeAnKEJvX9QNQ31RFOIPA4U3tfeYkSQQ0mlHJGR9aVS21St9jCs1m0dSAymYGpGlHYtIXLSNEXChiDgABzXfe-llMUxmmeZml9VZFgleDwgwEQhglHAECJW5IWPjDXpBNhA2mnAJToJQkkAEIjT-wgTSdWM46o-PsBO9YEAAGvYk1Q7alN45JnDHnU96lNYET6pNwiC8LOAYohllVf6PiS6a0sUXL_a2WhCt7p4fbS14iF9gqlCw9QBFqkRRRcj1yZyjAgicCbcBaxYOBELONCGyABjGBkBpq58hLSr4fhRDEIRyOIIBeKHQA)
|
||||
|
||||
<!-- vue3Demo:end -->
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
<summary>Vue 2 <a href="https://stackblitz.com/edit/vue-echarts-vue-2-global?file=index.html">Demo →</a></summary>
|
||||
|
||||
<!-- vue2Scripts:start -->
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.0.0-rc.3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.0.2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.0.0-rc.1"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.5"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@6.3.2"></script>
|
||||
```
|
||||
<!-- vue2Scripts:end -->
|
||||
|
||||
@ -320,8 +254,6 @@ app.component('v-chart', VueECharts)
|
||||
Vue.component("v-chart", VueECharts);
|
||||
```
|
||||
|
||||
[Demo →](https://codepen.io/Justineo/pen/gOLGxJR)
|
||||
|
||||
</details>
|
||||
|
||||
可以在[这里](https://github.com/ecomfe/vue-echarts/tree/main/src/demo)查看更多例子。
|
||||
@ -344,6 +276,8 @@ Vue.component("v-chart", VueECharts);
|
||||
|
||||
ECharts 的万能接口。修改这个 prop 会触发 ECharts 实例的 `setOption` 方法。查看[详情 →](https://echarts.apache.org/zh/option.html)
|
||||
|
||||
> 💡 在没有指定 `update-options` 时,如果直接修改 `option` 对象而引用保持不变,`setOption` 方法调用时将默认指定 `notMerge: false`;否则,如果为 `option` 绑定一个新的引用,将指定 `notMerge: true`。
|
||||
|
||||
- `update-options: object`
|
||||
|
||||
图表更新的配置项。请参考 `echartsInstance.setOption` 的 `opts` 参数。[前往 →](https://echarts.apache.org/zh/api.html#echartsInstance.setOption)
|
||||
@ -372,72 +306,20 @@ Vue.component("v-chart", VueECharts);
|
||||
|
||||
在性能敏感(数据量很大)的场景下,我们最好对于 `option` prop 绕过 Vue 的响应式系统。当将 `manual-update` prop 指定为 `true` 且不传入 `option` prop 时,数据将不会被监听。然后,需要用 `ref` 获取组件实例以后手动调用 `setOption` 方法来更新图表。
|
||||
|
||||
### Provide / Inject
|
||||
|
||||
Vue-ECharts 为 `theme`、`init-options`、`update-options` 和 `loading-options` 提供了 provide/inject API,以通过上下文配置选项。例如:可以通过如下方式来使用 provide API 为 `init-options` 提供上下文配置:
|
||||
|
||||
<details open>
|
||||
<summary>Vue 3</summary>
|
||||
|
||||
```js
|
||||
import { INIT_OPTIONS_KEY } from 'vue-echarts'
|
||||
import { provide } from 'vue'
|
||||
|
||||
// composition API
|
||||
provide(INIT_OPTIONS_KEY, ...)
|
||||
|
||||
// options API
|
||||
{
|
||||
provide: {
|
||||
[INIT_OPTIONS_KEY]: { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
|
||||
```js
|
||||
import { INIT_OPTIONS_KEY } from 'vue-echarts'
|
||||
|
||||
// in component options
|
||||
{
|
||||
provide: {
|
||||
[INIT_OPTIONS_KEY]: { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### 方法
|
||||
|
||||
- `setOption` [→](https://echarts.apache.org/zh/api.html#echartsInstance.setOption)
|
||||
- `getWidth` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getWidth)
|
||||
- `getHeight` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getHeight)
|
||||
- `getDom` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getDom)
|
||||
- `getOption` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getOption)
|
||||
- `resize` [→](https://echarts.apache.org/zh/api.html#echartsInstance.resize)
|
||||
- `dispatchAction` [→](https://echarts.apache.org/zh/api.html#echartsInstance.dispatchAction)
|
||||
- `convertToPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.convertToPixel)
|
||||
- `convertFromPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.convertFromPixel)
|
||||
- `containPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.containPixel)
|
||||
- `showLoading` [→](https://echarts.apache.org/zh/api.html#echartsInstance.showLoading)
|
||||
- `hideLoading` [→](https://echarts.apache.org/zh/api.html#echartsInstance.hideLoading)
|
||||
- `containPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.containPixel)
|
||||
- `getDataURL` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getDataURL)
|
||||
- `getConnectedDataURL` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getConnectedDataURL)
|
||||
- `clear` [→](https://echarts.apache.org/zh/api.html#echartsInstance.clear)
|
||||
- `dispose` [→](https://echarts.apache.org/zh/api.html#echartsInstance.dispose)
|
||||
|
||||
### 静态方法
|
||||
|
||||
静态方法请直接通过 [`echarts` 本身](https://echarts.apache.org/zh/api.html#echarts)进行调用。
|
||||
|
||||
### 事件
|
||||
|
||||
可以使用 Vue 的 `v-on` 指令绑定事件。
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<v-chart :option="option" @highlight="handleHighlight" />
|
||||
</template>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> 仅支持 `.once` 修饰符,因为其它修饰符都与 DOM 事件机制强耦合。
|
||||
|
||||
Vue-ECharts 支持如下事件:
|
||||
|
||||
- `highlight` [→](https://echarts.apache.org/zh/api.html#events.highlight)
|
||||
@ -486,6 +368,89 @@ Vue-ECharts 支持如下事件:
|
||||
|
||||
请参考支持的事件列表。[前往 →](https://echarts.apache.org/zh/api.html#events)
|
||||
|
||||
### Provide / Inject
|
||||
|
||||
Vue-ECharts 为 `theme`、`init-options`、`update-options` 和 `loading-options` 提供了 provide/inject API,以通过上下文配置选项。例如:可以通过如下方式来使用 provide API 为 `init-options` 提供上下文配置:
|
||||
|
||||
<details>
|
||||
<summary>Vue 3</summary>
|
||||
|
||||
```js
|
||||
import { THEME_KEY } from 'vue-echarts'
|
||||
import { provide } from 'vue'
|
||||
|
||||
// 组合式 API
|
||||
provide(THEME_KEY, 'dark')
|
||||
|
||||
// 选项式 API
|
||||
{
|
||||
provide: {
|
||||
[THEME_KEY]: 'dark'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Vue 2</summary>
|
||||
|
||||
```js
|
||||
import { THEME_KEY } from 'vue-echarts'
|
||||
|
||||
// 组件选项中
|
||||
{
|
||||
provide: {
|
||||
[THEME_KEY]: 'dark'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> 在 Vue 2 中,如果你想动态地改变这些选项,那么你需要提供一个对象。
|
||||
>
|
||||
> ```js
|
||||
> // 组件选项中
|
||||
> {
|
||||
> data () {
|
||||
> return {
|
||||
> theme: { value: 'dark' }
|
||||
> }
|
||||
> },
|
||||
> provide () {
|
||||
> return {
|
||||
> [THEME_KEY]: this.theme
|
||||
> }
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
|
||||
</details>
|
||||
|
||||
### 方法
|
||||
|
||||
- `setOption` [→](https://echarts.apache.org/zh/api.html#echartsInstance.setOption)
|
||||
- `getWidth` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getWidth)
|
||||
- `getHeight` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getHeight)
|
||||
- `getDom` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getDom)
|
||||
- `getOption` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getOption)
|
||||
- `resize` [→](https://echarts.apache.org/zh/api.html#echartsInstance.resize)
|
||||
- `dispatchAction` [→](https://echarts.apache.org/zh/api.html#echartsInstance.dispatchAction)
|
||||
- `convertToPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.convertToPixel)
|
||||
- `convertFromPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.convertFromPixel)
|
||||
- `containPixel` [→](https://echarts.apache.org/zh/api.html#echartsInstance.containPixel)
|
||||
- `showLoading` [→](https://echarts.apache.org/zh/api.html#echartsInstance.showLoading)
|
||||
- `hideLoading` [→](https://echarts.apache.org/zh/api.html#echartsInstance.hideLoading)
|
||||
- `getDataURL` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getDataURL)
|
||||
- `getConnectedDataURL` [→](https://echarts.apache.org/zh/api.html#echartsInstance.getConnectedDataURL)
|
||||
- `clear` [→](https://echarts.apache.org/zh/api.html#echartsInstance.clear)
|
||||
- `dispose` [→](https://echarts.apache.org/zh/api.html#echartsInstance.dispose)
|
||||
|
||||
### 静态方法
|
||||
|
||||
静态方法请直接通过 [`echarts` 本身](https://echarts.apache.org/zh/api.html#echarts)进行调用。
|
||||
|
||||
## 迁移到 v6
|
||||
|
||||
> 💡 请确保同时查阅 ECharts 5 的[升级指南](https://echarts.apache.org/zh/tutorial.html#ECharts%205%20%E5%8D%87%E7%BA%A7%E6%8C%87%E5%8D%97)。
|
||||
@ -494,7 +459,7 @@ Vue-ECharts 支持如下事件:
|
||||
|
||||
### Vue 2 支持
|
||||
|
||||
- 要在 Vue 2 中使用 Vue-ECharts,现在必须安装 `@vue/composition-api`。
|
||||
- 要在 `vue@2.7.0` 之前的版本中使用 Vue-ECharts,必须安装 `@vue/composition-api`。
|
||||
|
||||
### Prop
|
||||
|
||||
|
||||
16381
package-lock.json
generated
16381
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
83
package.json
83
package.json
@ -1,73 +1,82 @@
|
||||
{
|
||||
"name": "vue-echarts",
|
||||
"version": "6.3.3",
|
||||
"description": "Vue.js component for Apache ECharts.",
|
||||
"version": "6.0.0-rc.1",
|
||||
"repository": "https://github.com/ecomfe/vue-echarts.git",
|
||||
"license": "MIT",
|
||||
"author": "GU Yiling <justice360@gmail.com>",
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build:demo": "vue-cli-service build",
|
||||
"build": "npm run readme && rimraf dist && rollup -c rollup.config.js",
|
||||
"build": "pnpm run docs && rimraf dist && pnpm run build:2 && pnpm run build:3 && vue-demi-switch 3",
|
||||
"build:2": "vue-demi-switch 2 vue2 && rollup -c rollup.vue2.config.js",
|
||||
"build:3": "vue-demi-switch 3 && rollup -c rollup.config.js",
|
||||
"lint": "vue-cli-service lint",
|
||||
"prepare": "npm run build",
|
||||
"build:demo": "vue-cli-service build",
|
||||
"docs": "node -r esm ./scripts/docs.js",
|
||||
"postinstall": "node ./scripts/postinstall.js",
|
||||
"readme": "node -r esm ./scripts/readme.js"
|
||||
"prepare": "pnpm run build"
|
||||
},
|
||||
"main": "dist/index.cjs.min.js",
|
||||
"module": "dist/index.esm.min.js",
|
||||
"unpkg": "dist/index.umd.min.js",
|
||||
"jsdelivr": "dist/index.umd.min.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"scripts/postinstall.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"resize-detector": "^0.3.0",
|
||||
"vue-demi": "^0.7.1"
|
||||
"vue-demi": "^0.13.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.10",
|
||||
"@rollup/plugin-node-resolve": "^11.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||
"@typescript-eslint/parser": "^2.33.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
||||
"@typescript-eslint/parser": "^4.15.1",
|
||||
"@vue/cli-plugin-babel": "^5.0.4",
|
||||
"@vue/cli-plugin-eslint": "^5.0.4",
|
||||
"@vue/cli-plugin-typescript": "^5.0.4",
|
||||
"@vue/cli-service": "^5.0.4",
|
||||
"@vue/compiler-sfc": "^3.2.33",
|
||||
"@vue/composition-api": "^1.7.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/eslint-config-typescript": "^5.0.2",
|
||||
"codesandbox": "^2.2.1",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"comment-mark": "^1.0.0",
|
||||
"echarts": "^5.0.2",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^7.0.0-0",
|
||||
"core-js": "^3.23.0",
|
||||
"echarts": "^5.3.2",
|
||||
"echarts-liquidfill": "^3.1.0",
|
||||
"eslint": "^7.20.0",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-vue": "^8.7.1",
|
||||
"esm": "^3.2.25",
|
||||
"postcss": "^8.2.5",
|
||||
"postcss": "^8.3.0",
|
||||
"postcss-loader": "^5.0.0",
|
||||
"postcss-nested": "^4.2.3",
|
||||
"prettier": "^1.19.1",
|
||||
"postcss-nested": "^5.0.5",
|
||||
"prettier": "^2.6.2",
|
||||
"qs": "^6.10.5",
|
||||
"raw-loader": "^4.0.2",
|
||||
"resize-detector": "^0.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.38.5",
|
||||
"rollup-plugin-dts": "^2.0.1",
|
||||
"rollup-plugin-postcss": "^4.0.0",
|
||||
"rollup": "^2.72.1",
|
||||
"rollup-plugin-dts": "^4.2.1",
|
||||
"rollup-plugin-styles": "^4.0.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-typescript2": "^0.29.0",
|
||||
"typescript": "^4.1.3",
|
||||
"vue": "^3.0.5"
|
||||
"rollup-plugin-ts": "^2.0.7",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "4.6.4",
|
||||
"vue": "^3.2.33",
|
||||
"vue2": "npm:vue@^2.7.14",
|
||||
"webpack": "^5.72.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.2",
|
||||
"echarts": "^5.0.2",
|
||||
"vue": "^2.6.12 || ^3.0.0"
|
||||
"@vue/composition-api": "^1.0.5",
|
||||
"echarts": "^5.1.2",
|
||||
"vue": "^2.6.12 || ^3.1.1"
|
||||
},
|
||||
"jsdelivr": "dist/index.umd.min.js",
|
||||
"license": "MIT",
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"repository": "https://github.com/ecomfe/vue-echarts.git",
|
||||
"types": "dist/index.d.ts"
|
||||
}
|
||||
|
||||
7838
pnpm-lock.yaml
generated
Normal file
7838
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,25 +1,38 @@
|
||||
import typescript from "rollup-plugin-typescript2";
|
||||
import typescript from "rollup-plugin-ts";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
import resolve from "@rollup/plugin-node-resolve";
|
||||
import postcss from "rollup-plugin-postcss";
|
||||
import dts from "rollup-plugin-dts";
|
||||
import { injectVueDemi, ingoreCss } from "./scripts/rollup";
|
||||
import styles from "rollup-plugin-styles";
|
||||
import { injectVueDemi } from "./scripts/rollup";
|
||||
|
||||
/** @type {import('rollup').RollupOptions} */
|
||||
/** @type {import('rollup').RollupOptions[]} */
|
||||
const options = [
|
||||
{
|
||||
input: "src/index.ts",
|
||||
plugins: [typescript(), postcss()],
|
||||
plugins: [
|
||||
typescript({
|
||||
tsconfig: resolvedConfig => ({ ...resolvedConfig, declaration: true }),
|
||||
hook: {
|
||||
outputPath: (path, kind) =>
|
||||
kind === "declaration" ? "dist/index.d.ts" : path
|
||||
}
|
||||
}),
|
||||
styles()
|
||||
],
|
||||
external: ["vue-demi", "echarts/core", "resize-detector"],
|
||||
output: {
|
||||
file: "dist/index.esm.js",
|
||||
format: "esm",
|
||||
sourcemap: true
|
||||
}
|
||||
},
|
||||
{
|
||||
input: "src/index.ts",
|
||||
plugins: [typescript(), styles()],
|
||||
external: ["vue-demi", "echarts/core", "resize-detector"],
|
||||
output: [
|
||||
{
|
||||
file: "dist/index.esm.js",
|
||||
format: "es",
|
||||
sourcemap: true
|
||||
},
|
||||
{
|
||||
file: "dist/index.esm.min.js",
|
||||
format: "es",
|
||||
format: "esm",
|
||||
sourcemap: true,
|
||||
plugins: [
|
||||
terser({
|
||||
@ -52,7 +65,7 @@ const options = [
|
||||
},
|
||||
{
|
||||
input: "src/global.ts",
|
||||
plugins: [resolve(), typescript(), postcss()],
|
||||
plugins: [resolve(), typescript(), styles()],
|
||||
external: ["vue-demi", "echarts", "echarts/core"],
|
||||
output: [
|
||||
{
|
||||
@ -89,14 +102,6 @@ const options = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
input: "src/index.ts",
|
||||
plugins: [ingoreCss, dts()],
|
||||
output: {
|
||||
file: "dist/index.d.ts",
|
||||
format: "es"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
15
rollup.vue2.config.js
Normal file
15
rollup.vue2.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
import dts from "rollup-plugin-dts";
|
||||
|
||||
/** @type {import('rollup').RollupOptions[]} */
|
||||
const options = [
|
||||
{
|
||||
input: "src/index.vue2.d.ts",
|
||||
plugins: [dts()],
|
||||
output: {
|
||||
file: "dist/index.vue2.d.ts",
|
||||
format: "esm"
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default options;
|
||||
@ -1,7 +1,6 @@
|
||||
import fs from "fs";
|
||||
import { resolve } from "path";
|
||||
import commentMark from "comment-mark";
|
||||
import { getParameters } from "codesandbox/lib/api/define";
|
||||
import { name, version } from "../package.json";
|
||||
|
||||
const { readFile, writeFile } = fs.promises;
|
||||
@ -9,16 +8,15 @@ const { readFile, writeFile } = fs.promises;
|
||||
const CDN_PREFIX = "https://cdn.jsdelivr.net/npm/";
|
||||
|
||||
const DEP_VERSIONS = {
|
||||
"vue@3": "3.0.7",
|
||||
"vue@2": "2.6.12",
|
||||
"@vue/composition-api": "1.0.0-rc.3",
|
||||
echarts: "5.0.2",
|
||||
"vue@3": "3.2.37",
|
||||
"vue@2": "2.7.5",
|
||||
echarts: "5.3.3",
|
||||
[name]: version
|
||||
};
|
||||
|
||||
const markConfig = {
|
||||
vue3Scripts: ["vue@3", "echarts", name],
|
||||
vue2Scripts: ["vue@2", "@vue/composition-api", "echarts", name]
|
||||
vue2Scripts: ["vue@2", "echarts", name]
|
||||
};
|
||||
|
||||
function getScripts(version) {
|
||||
@ -40,38 +38,6 @@ const scripts = {
|
||||
3: getScripts(3)
|
||||
};
|
||||
|
||||
async function getSandboxParams(version) {
|
||||
const [html, js, css] = await Promise.all(
|
||||
["index.html", `vue${version}.js`, "index.css"].map(async name => {
|
||||
const file = resolve(__dirname, `./sandbox/${name}`);
|
||||
return readFile(file, "utf-8");
|
||||
})
|
||||
);
|
||||
return {
|
||||
files: {
|
||||
"index.html": {
|
||||
content: `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
${css}</style>
|
||||
</head>
|
||||
<body>
|
||||
${html}${scripts[version]}
|
||||
<script>
|
||||
${js}</script>
|
||||
</body>
|
||||
</html>`
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function getDemoLink(version) {
|
||||
const parameters = getParameters(await getSandboxParams(version));
|
||||
return `[Demo →](${`https://codesandbox.io/api/v1/sandboxes/define?parameters=${parameters}`})`;
|
||||
}
|
||||
|
||||
const README_FILES = ["README.md", "README.zh-Hans.md"].map(name =>
|
||||
resolve(__dirname, "..", name)
|
||||
);
|
||||
@ -79,19 +45,15 @@ const README_FILES = ["README.md", "README.zh-Hans.md"].map(name =>
|
||||
function exec() {
|
||||
return Promise.all(
|
||||
README_FILES.map(async file => {
|
||||
const content = await readFile(file, "utf-8");
|
||||
|
||||
const [link2, link3] = await Promise.all([2, 3].map(getDemoLink));
|
||||
const content = await readFile(file, "utf8");
|
||||
|
||||
return writeFile(
|
||||
file,
|
||||
commentMark(content, {
|
||||
vue2Scripts: getCodeBlock(scripts[2]),
|
||||
vue3Scripts: getCodeBlock(scripts[3]),
|
||||
vue2Demo: `\n${link2}\n`,
|
||||
vue3Demo: `\n${link3}\n`
|
||||
vue3Scripts: getCodeBlock(scripts[3])
|
||||
}),
|
||||
"utf-8"
|
||||
"utf8"
|
||||
);
|
||||
})
|
||||
);
|
||||
@ -11,10 +11,10 @@ const typesPaths = {
|
||||
|
||||
function switchVersion(version) {
|
||||
const typesPath = typesPaths[version];
|
||||
const package = JSON.parse(fs.readFileSync(packageFile, "utf-8"));
|
||||
const current = package.types || package.typings;
|
||||
if (typesPath !== current) {
|
||||
fs.writeFileSync(JSON.stringify(package, null, " "));
|
||||
const package = JSON.parse(fs.readFileSync(packageFile, "utf8"));
|
||||
if (typesPath !== package.types) {
|
||||
package.types = typesPath;
|
||||
fs.writeFileSync(packageFile, JSON.stringify(package, null, " "), "utf8");
|
||||
}
|
||||
console.log(`[vue-echarts] Switched to Vue ${version} environment.`);
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { readFileSync } from "fs";
|
||||
|
||||
const VUE_DEMI_IIFE = readFileSync(
|
||||
require.resolve("vue-demi/lib/index.iife.js"),
|
||||
"utf-8"
|
||||
"utf8"
|
||||
);
|
||||
|
||||
/** @type {import('rollup').Plugin} */
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
Vue.component("v-chart", VueECharts);
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data() {
|
||||
return {
|
||||
option: {
|
||||
textStyle: {
|
||||
fontFamily: 'Inter, "Helvetica Neue", Arial, sans-serif'
|
||||
},
|
||||
title: {
|
||||
text: "Traffic Sources",
|
||||
left: "center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
left: "left",
|
||||
data: [
|
||||
"Direct",
|
||||
"Email",
|
||||
"Ad Networks",
|
||||
"Video Ads",
|
||||
"Search Engines"
|
||||
]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Traffic Sources",
|
||||
type: "pie",
|
||||
radius: "55%",
|
||||
center: ["50%", "60%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" }
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -1,54 +0,0 @@
|
||||
Vue.createApp({
|
||||
data() {
|
||||
return {
|
||||
option: {
|
||||
textStyle: {
|
||||
fontFamily: 'Inter, "Helvetica Neue", Arial, sans-serif'
|
||||
},
|
||||
title: {
|
||||
text: "Traffic Sources",
|
||||
left: "center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
left: "left",
|
||||
data: [
|
||||
"Direct",
|
||||
"Email",
|
||||
"Ad Networks",
|
||||
"Video Ads",
|
||||
"Search Engines"
|
||||
]
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Traffic Sources",
|
||||
type: "pie",
|
||||
radius: "55%",
|
||||
center: ["50%", "60%"],
|
||||
data: [
|
||||
{ value: 335, name: "Direct" },
|
||||
{ value: 310, name: "Email" },
|
||||
{ value: 234, name: "Ad Networks" },
|
||||
{ value: 135, name: "Video Ads" },
|
||||
{ value: 1548, name: "Search Engines" }
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
})
|
||||
.component("v-chart", VueECharts)
|
||||
.mount("#app");
|
||||
171
src/ECharts.ts
171
src/ECharts.ts
@ -1,10 +1,8 @@
|
||||
/* eslint-disable vue/multi-word-component-names */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
unref,
|
||||
shallowRef,
|
||||
toRef,
|
||||
toRefs,
|
||||
watch,
|
||||
computed,
|
||||
@ -13,20 +11,24 @@ import {
|
||||
onUnmounted,
|
||||
h,
|
||||
nextTick,
|
||||
PropType,
|
||||
watchEffect,
|
||||
Vue2
|
||||
getCurrentInstance,
|
||||
Vue2,
|
||||
type PropType,
|
||||
type InjectionKey
|
||||
} from "vue-demi";
|
||||
import { init as initChart } from "echarts/core";
|
||||
import {
|
||||
import type {
|
||||
EChartsType,
|
||||
EventTarget,
|
||||
Option,
|
||||
Theme,
|
||||
ThemeInjection,
|
||||
InitOptions,
|
||||
InitOptionsInjection,
|
||||
UpdateOptions,
|
||||
UpdateOptionsInjection
|
||||
UpdateOptionsInjection,
|
||||
Emits
|
||||
} from "./types";
|
||||
import {
|
||||
usePublicAPI,
|
||||
@ -35,8 +37,8 @@ import {
|
||||
useLoading,
|
||||
loadingProps
|
||||
} from "./composables";
|
||||
import { omitOn, unwrapInjected } from "./utils";
|
||||
import "./style.css";
|
||||
import { omitOn } from "./utils";
|
||||
|
||||
const TAG_NAME = "x-vue-echarts";
|
||||
|
||||
@ -44,9 +46,11 @@ if (Vue2) {
|
||||
Vue2.config.ignoredElements.push(TAG_NAME);
|
||||
}
|
||||
|
||||
export const THEME_KEY = "ecTheme";
|
||||
export const INIT_OPTIONS_KEY = "ecInitOptions";
|
||||
export const UPDATE_OPTIONS_KEY = "ecUpdateOptions";
|
||||
export const THEME_KEY = "ecTheme" as unknown as InjectionKey<ThemeInjection>;
|
||||
export const INIT_OPTIONS_KEY =
|
||||
"ecInitOptions" as unknown as InjectionKey<InitOptionsInjection>;
|
||||
export const UPDATE_OPTIONS_KEY =
|
||||
"ecUpdateOptions" as unknown as InjectionKey<UpdateOptionsInjection>;
|
||||
export { LOADING_OPTIONS_KEY } from "./composables";
|
||||
|
||||
export default defineComponent({
|
||||
@ -63,42 +67,37 @@ export default defineComponent({
|
||||
...autoresizeProps,
|
||||
...loadingProps
|
||||
},
|
||||
emits: [] as unknown as Emits,
|
||||
inheritAttrs: false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// @ts-expect-error
|
||||
setup(props, { attrs, listeners }) {
|
||||
const root = ref<HTMLElement>();
|
||||
setup(props, { attrs }) {
|
||||
const root = shallowRef<HTMLElement>();
|
||||
const chart = shallowRef<EChartsType>();
|
||||
const manualOption = shallowRef<Option>();
|
||||
const defaultTheme = inject(THEME_KEY, null) as ThemeInjection;
|
||||
const defaultInitOptions = inject(
|
||||
INIT_OPTIONS_KEY,
|
||||
null
|
||||
) as InitOptionsInjection;
|
||||
const defaultUpdateOptions = inject(
|
||||
UPDATE_OPTIONS_KEY,
|
||||
null
|
||||
) as UpdateOptionsInjection;
|
||||
const defaultTheme = inject(THEME_KEY, null);
|
||||
const defaultInitOptions = inject(INIT_OPTIONS_KEY, null);
|
||||
const defaultUpdateOptions = inject(UPDATE_OPTIONS_KEY, null);
|
||||
|
||||
const { autoresize, manualUpdate, loading, loadingOptions } = toRefs(props);
|
||||
|
||||
const realOption = computed(
|
||||
() => manualOption.value || props.option || Object.create(null)
|
||||
() => manualOption.value || props.option || null
|
||||
);
|
||||
const realTheme = computed(
|
||||
() => props.theme || unwrapInjected(defaultTheme, {})
|
||||
);
|
||||
const realTheme = computed(() => props.theme || unref(defaultTheme) || {});
|
||||
const realInitOptions = computed(
|
||||
() => props.initOptions || unref(defaultInitOptions) || {}
|
||||
() => props.initOptions || unwrapInjected(defaultInitOptions, {})
|
||||
);
|
||||
const realUpdateOptions = computed(
|
||||
() => props.updateOptions || unref(defaultUpdateOptions) || {}
|
||||
() => props.updateOptions || unwrapInjected(defaultUpdateOptions, {})
|
||||
);
|
||||
|
||||
const { autoresize, manualUpdate, loading } = toRefs(props);
|
||||
const theme = toRef(props, "theme");
|
||||
const initOptions = toRef(props, "initOptions");
|
||||
const loadingOptions = toRef(props, "loadingOptions");
|
||||
|
||||
const nonEventAttrs = computed(() => omitOn(attrs));
|
||||
|
||||
// @ts-expect-error listeners for Vue 2 compatibility
|
||||
const listeners = getCurrentInstance().proxy.$listeners;
|
||||
|
||||
function init(option?: Option) {
|
||||
if (chart.value || !root.value) {
|
||||
if (!root.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,35 +120,77 @@ export default defineComponent({
|
||||
.forEach(key => {
|
||||
// onClick -> c + lick
|
||||
// onZr:click -> z + r:click
|
||||
const event = key.charAt(2).toLowerCase() + key.slice(3);
|
||||
let event = key.charAt(2).toLowerCase() + key.slice(3);
|
||||
|
||||
// clickOnce -> ~click
|
||||
// zr:clickOnce -> ~zr:click
|
||||
if (event.substring(event.length - 4) === "Once") {
|
||||
event = `~${event.substring(0, event.length - 4)}`;
|
||||
}
|
||||
|
||||
realListeners[event] = attrs[key];
|
||||
});
|
||||
}
|
||||
|
||||
Object.keys(realListeners).forEach(key => {
|
||||
const handler = realListeners[key] as any;
|
||||
let handler = realListeners[key];
|
||||
|
||||
if (!handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.indexOf("zr:") === 0) {
|
||||
instance.getZr().on(key.slice(3).toLowerCase(), handler);
|
||||
} else {
|
||||
instance.on(key.toLowerCase(), handler);
|
||||
let event = key.toLowerCase();
|
||||
if (event.charAt(0) === "~") {
|
||||
event = event.substring(1);
|
||||
handler.__once__ = true;
|
||||
}
|
||||
});
|
||||
|
||||
instance.setOption(option || realOption.value, realUpdateOptions.value);
|
||||
let target: EventTarget = instance;
|
||||
if (event.indexOf("zr:") === 0) {
|
||||
target = instance.getZr();
|
||||
event = event.substring(3);
|
||||
}
|
||||
|
||||
if (handler.__once__) {
|
||||
delete handler.__once__;
|
||||
|
||||
const raw = handler;
|
||||
|
||||
handler = (...args: any[]) => {
|
||||
raw(...args);
|
||||
target.off(event, handler);
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore EChartsType["on"] is not compatible with ZRenderType["on"]
|
||||
// but it's okay here
|
||||
target.on(event, handler);
|
||||
});
|
||||
|
||||
function resize() {
|
||||
if (instance && !instance.isDisposed()) {
|
||||
instance.resize();
|
||||
}
|
||||
}
|
||||
// Make sure the chart fits the container in next UI render (after current task)
|
||||
nextTick(resize);
|
||||
setTimeout(resize);
|
||||
|
||||
function commit() {
|
||||
const opt = option || realOption.value;
|
||||
if (opt) {
|
||||
instance.setOption(opt, realUpdateOptions.value);
|
||||
}
|
||||
}
|
||||
|
||||
if (autoresize.value) {
|
||||
// Try to make chart fit to container in case container size
|
||||
// is changed synchronously or in already queued microtasks
|
||||
nextTick(() => {
|
||||
resize();
|
||||
commit();
|
||||
});
|
||||
} else {
|
||||
commit();
|
||||
}
|
||||
}
|
||||
|
||||
function setOption(option: Option, updateOptions?: UpdateOptions) {
|
||||
@ -160,10 +201,7 @@ export default defineComponent({
|
||||
if (!chart.value) {
|
||||
init(option);
|
||||
} else {
|
||||
chart.value.setOption(option, {
|
||||
...realUpdateOptions.value,
|
||||
...updateOptions
|
||||
});
|
||||
chart.value.setOption(option, updateOptions || {});
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,14 +224,17 @@ export default defineComponent({
|
||||
if (!manualUpdate) {
|
||||
unwatchOption = watch(
|
||||
() => props.option,
|
||||
option => {
|
||||
(option, oldOption) => {
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
if (!chart.value) {
|
||||
init();
|
||||
} else {
|
||||
chart.value.setOption(option, props.updateOptions);
|
||||
chart.value.setOption(option, {
|
||||
notMerge: option.value !== oldOption?.value,
|
||||
...realUpdateOptions.value
|
||||
});
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
@ -206,7 +247,7 @@ export default defineComponent({
|
||||
);
|
||||
|
||||
watch(
|
||||
[theme, initOptions],
|
||||
[realTheme, realInitOptions],
|
||||
() => {
|
||||
cleanup();
|
||||
init();
|
||||
@ -222,36 +263,32 @@ export default defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
const publicApi = usePublicAPI(chart, init);
|
||||
const publicApi = usePublicAPI(chart);
|
||||
|
||||
useLoading(chart, loading, loadingOptions);
|
||||
|
||||
useAutoresize(chart, autoresize, root, realOption);
|
||||
useAutoresize(chart, autoresize, root);
|
||||
|
||||
onMounted(() => {
|
||||
if (props.option) {
|
||||
init();
|
||||
}
|
||||
init();
|
||||
});
|
||||
|
||||
onUnmounted(cleanup);
|
||||
|
||||
const exposed = {
|
||||
return {
|
||||
chart,
|
||||
root,
|
||||
setOption,
|
||||
nonEventAttrs,
|
||||
...publicApi
|
||||
};
|
||||
Object.defineProperty(exposed, "chart", {
|
||||
get() {
|
||||
return unref(chart);
|
||||
}
|
||||
});
|
||||
|
||||
return exposed;
|
||||
},
|
||||
render() {
|
||||
const attrs = { ...this.nonEventAttrs };
|
||||
// Vue 3 and Vue 2 have different vnode props format:
|
||||
// See https://v3-migration.vuejs.org/breaking-changes/render-function-api.html#vnode-props-format
|
||||
const attrs = (
|
||||
Vue2 ? { attrs: this.nonEventAttrs } : { ...this.nonEventAttrs }
|
||||
) as any;
|
||||
attrs.ref = "root";
|
||||
attrs.class = attrs.class ? ["echarts"].concat(attrs.class) : "echarts";
|
||||
return h(TAG_NAME, attrs);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Ref } from "vue-demi";
|
||||
import { EChartsType, Option } from "../types";
|
||||
import { EChartsType } from "../types";
|
||||
|
||||
const METHOD_NAMES = [
|
||||
"getWidth",
|
||||
@ -19,22 +19,18 @@ const METHOD_NAMES = [
|
||||
"isDisposed",
|
||||
"dispose"
|
||||
] as const;
|
||||
|
||||
type MethodName = typeof METHOD_NAMES[number];
|
||||
|
||||
type PublicMethods = Pick<EChartsType, MethodName>;
|
||||
|
||||
export function usePublicAPI(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
init: (option?: Option) => void
|
||||
) {
|
||||
chart: Ref<EChartsType | undefined>
|
||||
): PublicMethods {
|
||||
function makePublicMethod<T extends MethodName>(
|
||||
name: T
|
||||
): (...args: Parameters<EChartsType[T]>) => ReturnType<EChartsType[T]> {
|
||||
return (...args) => {
|
||||
if (!chart.value) {
|
||||
init();
|
||||
}
|
||||
|
||||
if (!chart.value) {
|
||||
throw new Error("ECharts is not initialized yet.");
|
||||
}
|
||||
@ -42,12 +38,6 @@ export function usePublicAPI(
|
||||
};
|
||||
}
|
||||
|
||||
function makeAnyMethod<T extends MethodName>(
|
||||
name: T
|
||||
): (...args: any[]) => ReturnType<EChartsType[T]> {
|
||||
return makePublicMethod(name) as any;
|
||||
}
|
||||
|
||||
function makePublicMethods(): PublicMethods {
|
||||
const methods = Object.create(null);
|
||||
METHOD_NAMES.forEach(name => {
|
||||
@ -57,10 +47,5 @@ export function usePublicAPI(
|
||||
return methods as PublicMethods;
|
||||
}
|
||||
|
||||
return {
|
||||
...makePublicMethods(),
|
||||
dispatchAction: makeAnyMethod("dispatchAction"),
|
||||
getDataURL: makeAnyMethod("getDataURL"),
|
||||
getConnectedDataURL: makeAnyMethod("getConnectedDataURL")
|
||||
};
|
||||
return makePublicMethods();
|
||||
}
|
||||
|
||||
@ -1,37 +1,19 @@
|
||||
import { Ref, watch } from "vue-demi";
|
||||
import { throttle } from "echarts/core";
|
||||
import { addListener, removeListener, ResizeCallback } from "resize-detector";
|
||||
import { EChartsType, Option } from "../types";
|
||||
import { EChartsType } from "../types";
|
||||
|
||||
export function useAutoresize(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
autoresize: Ref<boolean>,
|
||||
root: Ref<HTMLElement | undefined>,
|
||||
option: Ref<Option>
|
||||
root: Ref<HTMLElement | undefined>
|
||||
): void {
|
||||
let resizeListener: ResizeCallback | null = null;
|
||||
let lastArea = 0;
|
||||
|
||||
function getArea() {
|
||||
const el = root.value;
|
||||
if (!el) {
|
||||
return 0;
|
||||
}
|
||||
return el.offsetWidth * el.offsetHeight;
|
||||
}
|
||||
|
||||
watch([root, chart, autoresize], ([root, chart, autoresize], _, cleanup) => {
|
||||
if (root && chart && autoresize) {
|
||||
lastArea = getArea();
|
||||
resizeListener = throttle(() => {
|
||||
if (lastArea === 0) {
|
||||
chart.setOption(Object.create(null), true);
|
||||
chart.resize();
|
||||
chart.setOption(option.value, true);
|
||||
} else {
|
||||
chart.resize();
|
||||
}
|
||||
lastArea = getArea();
|
||||
chart.resize();
|
||||
}, 100);
|
||||
|
||||
addListener(root, resizeListener);
|
||||
@ -39,7 +21,6 @@ export function useAutoresize(
|
||||
|
||||
cleanup(() => {
|
||||
if (resizeListener && root) {
|
||||
lastArea = 0;
|
||||
removeListener(root, resizeListener);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,18 +1,28 @@
|
||||
import { inject, unref, computed, Ref, watchEffect } from "vue-demi";
|
||||
import { unwrapInjected } from "../utils";
|
||||
import {
|
||||
inject,
|
||||
computed,
|
||||
watchEffect,
|
||||
type Ref,
|
||||
type InjectionKey
|
||||
} from "vue-demi";
|
||||
import { EChartsType } from "../types";
|
||||
|
||||
export const LOADING_OPTIONS_KEY = "ecLoadingOptions";
|
||||
export const LOADING_OPTIONS_KEY =
|
||||
"ecLoadingOptions" as unknown as InjectionKey<
|
||||
UnknownRecord | Ref<UnknownRecord>
|
||||
>;
|
||||
|
||||
type UnknownRecord = Record<string, unknown>;
|
||||
|
||||
export function useLoading(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
loading: Ref<boolean>,
|
||||
loadingOptions: Ref<object | undefined>
|
||||
loadingOptions: Ref<UnknownRecord | undefined>
|
||||
): void {
|
||||
const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {}) as
|
||||
| object
|
||||
| Ref<object>;
|
||||
const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {});
|
||||
const realLoadingOptions = computed(() => ({
|
||||
...unref(defaultLoadingOptions),
|
||||
...unwrapInjected(defaultLoadingOptions, {}),
|
||||
...loadingOptions?.value
|
||||
}));
|
||||
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
<template>
|
||||
<main>
|
||||
<!-- <v-chart
|
||||
class="echarts" id="logo" :option="logo" :init-options="initOptions" autoresize /> -->
|
||||
<h1><a href="https://github.com/ecomfe/vue-echarts">Vue-ECharts</a></h1>
|
||||
<v-chart
|
||||
class="echarts"
|
||||
id="logo"
|
||||
:option="logo"
|
||||
:init-options="initOptions"
|
||||
autoresize
|
||||
/>
|
||||
<h1>
|
||||
<a href="https://github.com/ecomfe/vue-echarts">Vue-ECharts</a>
|
||||
</h1>
|
||||
<p class="desc">
|
||||
Vue.js component for Apache ECharts. (<a
|
||||
href="https://github.com/ecomfe/vue-echarts#readme"
|
||||
@ -11,9 +18,10 @@
|
||||
</p>
|
||||
|
||||
<h2 id="bar">
|
||||
<a href="#bar"
|
||||
>Bar chart <small>(with async data & custom theme)</small></a
|
||||
>
|
||||
<a href="#bar">
|
||||
Bar chart
|
||||
<small>(with async data & custom theme)</small>
|
||||
</a>
|
||||
<button
|
||||
:class="{
|
||||
round: true,
|
||||
@ -37,19 +45,26 @@
|
||||
@click="handleClick"
|
||||
/>
|
||||
</figure>
|
||||
<p v-if="seconds <= 0"><small>Loaded.</small></p>
|
||||
<p v-else>
|
||||
<small
|
||||
>Data coming in <b>{{ seconds }}</b> second{{
|
||||
seconds > 1 ? "s" : ""
|
||||
}}...</small
|
||||
>
|
||||
<p v-if="seconds <= 0">
|
||||
<small>Loaded.</small>
|
||||
</p>
|
||||
<p v-else>
|
||||
<small>
|
||||
Data coming in
|
||||
<b>{{ seconds }}</b>
|
||||
second{{ seconds > 1 ? "s" : "" }}...
|
||||
</small>
|
||||
</p>
|
||||
<p>
|
||||
<button @click="refresh" :disabled="seconds > 0">Refresh</button>
|
||||
</p>
|
||||
<p><button @click="refresh" :disabled="seconds > 0">Refresh</button></p>
|
||||
</section>
|
||||
|
||||
<h2 id="pie">
|
||||
<a href="#pie">Pie chart <small>(with action dispatch)</small></a>
|
||||
<a href="#pie">
|
||||
Pie chart
|
||||
<small>(with action dispatch)</small>
|
||||
</a>
|
||||
<button
|
||||
:class="{
|
||||
round: true,
|
||||
@ -71,7 +86,10 @@
|
||||
</section>
|
||||
|
||||
<h2 id="polar">
|
||||
<a href="#polar">Polar plot <small>(with built-in theme)</small></a>
|
||||
<a href="#polar">
|
||||
Polar plot
|
||||
<small>(with built-in theme)</small>
|
||||
</a>
|
||||
<button
|
||||
:class="{
|
||||
round: true,
|
||||
@ -100,7 +118,10 @@
|
||||
</section>
|
||||
|
||||
<h2 id="scatter">
|
||||
<a href="#scatter">Scatter plot <small>(with gradient)</small></a>
|
||||
<a href="#scatter">
|
||||
Scatter plot
|
||||
<small>(with gradient)</small>
|
||||
</a>
|
||||
<button
|
||||
:class="{
|
||||
round: true,
|
||||
@ -117,7 +138,10 @@
|
||||
</section>
|
||||
|
||||
<h2 id="map">
|
||||
<a href="#map">Map <small>(with GeoJSON & image converter)</small></a>
|
||||
<a href="#map">
|
||||
Map
|
||||
<small>(with GeoJSON & image converter)</small>
|
||||
</a>
|
||||
<button
|
||||
:class="{
|
||||
round: true,
|
||||
@ -128,7 +152,7 @@
|
||||
></button>
|
||||
</h2>
|
||||
<section v-if="expand.map">
|
||||
<figure style="background-color: #404a59;">
|
||||
<figure style="background-color: #404a59">
|
||||
<v-chart
|
||||
:option="map"
|
||||
:init-options="initOptions"
|
||||
@ -136,7 +160,9 @@
|
||||
autoresize
|
||||
/>
|
||||
</figure>
|
||||
<p><button @click="convert">Convert to image</button></p>
|
||||
<p>
|
||||
<button @click="convert">Convert to image</button>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- <h2 id="radar">
|
||||
@ -166,7 +192,7 @@
|
||||
<input id="async" type="checkbox" v-model="asyncCount" />
|
||||
<label for="async">Async</label>
|
||||
</p>
|
||||
</section> -->
|
||||
</section>-->
|
||||
|
||||
<h2 id="connect">
|
||||
<a href="#connect">Connectable charts</a>
|
||||
@ -219,13 +245,15 @@
|
||||
</h2>
|
||||
<section v-if="expand.flight">
|
||||
<p>
|
||||
<small
|
||||
>You may use <code>manual-update</code> prop for performance critical
|
||||
use cases.</small
|
||||
>
|
||||
<small>
|
||||
You may use
|
||||
<code>manual-update</code> prop for performance critical use cases.
|
||||
</small>
|
||||
</p>
|
||||
<p><button :disabled="flightLoaded" @click="loadFlights">Load</button></p>
|
||||
<figure style="background-color: #003;">
|
||||
<p>
|
||||
<button :disabled="flightLoaded" @click="loadFlights">Load</button>
|
||||
</p>
|
||||
<figure style="background-color: #003">
|
||||
<v-chart
|
||||
ref="flight"
|
||||
:init-options="initOptions"
|
||||
@ -238,10 +266,11 @@
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<a href="//github.com/Justineo">@Justineo</a>|<a
|
||||
href="//github.com/ecomfe/vue-echarts/blob/master/LICENSE"
|
||||
<a href="//github.com/Justineo">@Justineo</a>|
|
||||
<a href="//github.com/ecomfe/vue-echarts/blob/master/LICENSE"
|
||||
>MIT License</a
|
||||
>|<a href="//github.com/ecomfe/vue-echarts">View on GitHub</a>
|
||||
>|
|
||||
<a href="//github.com/ecomfe/vue-echarts">View on GitHub</a>
|
||||
</footer>
|
||||
|
||||
<aside :class="{ modal: true, open }" @click="open = false">
|
||||
@ -274,7 +303,13 @@
|
||||
import qs from "qs";
|
||||
import VChart from "../ECharts";
|
||||
|
||||
import * as echarts from "echarts/core";
|
||||
import {
|
||||
use,
|
||||
registerMap,
|
||||
registerTheme,
|
||||
connect,
|
||||
disconnect
|
||||
} from "echarts/core";
|
||||
import {
|
||||
BarChart,
|
||||
LineChart,
|
||||
@ -293,11 +328,26 @@ import {
|
||||
LegendComponent,
|
||||
TitleComponent,
|
||||
VisualMapComponent,
|
||||
DatasetComponent
|
||||
DatasetComponent,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent
|
||||
} from "echarts/components";
|
||||
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
|
||||
import "echarts-liquidfill";
|
||||
import logo from "./data/logo";
|
||||
import getBar from "./data/bar";
|
||||
import pie from "./data/pie";
|
||||
import polar from "./data/polar";
|
||||
import scatter from "./data/scatter";
|
||||
import map from "./data/map";
|
||||
import { c1, c2 } from "./data/connect";
|
||||
|
||||
const { use, registerMap, registerTheme } = echarts;
|
||||
// custom theme
|
||||
import theme from "./theme.json";
|
||||
|
||||
// Map of China
|
||||
import chinaMap from "./china.json";
|
||||
import worldMap from "./world.json";
|
||||
|
||||
use([
|
||||
BarChart,
|
||||
@ -317,25 +367,11 @@ use([
|
||||
VisualMapComponent,
|
||||
DatasetComponent,
|
||||
CanvasRenderer,
|
||||
SVGRenderer
|
||||
SVGRenderer,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent
|
||||
]);
|
||||
|
||||
// import "echarts-liquidfill";
|
||||
// import logo from "./data/logo";
|
||||
import getBar from "./data/bar";
|
||||
import pie from "./data/pie";
|
||||
import polar from "./data/polar";
|
||||
import scatter from "./data/scatter";
|
||||
import map from "./data/map";
|
||||
import { c1, c2 } from "./data/connect";
|
||||
|
||||
// custom theme
|
||||
import theme from "./theme.json";
|
||||
|
||||
// Map of China
|
||||
import chinaMap from "./china.json";
|
||||
import worldMap from "./world.json";
|
||||
|
||||
// registering map data
|
||||
registerMap("china", chinaMap);
|
||||
registerMap("world", worldMap);
|
||||
@ -344,6 +380,7 @@ registerMap("world", worldMap);
|
||||
registerTheme("ovilia-green", theme);
|
||||
|
||||
export default {
|
||||
name: "vue-echarts-demo",
|
||||
components: {
|
||||
VChart
|
||||
},
|
||||
@ -351,6 +388,7 @@ export default {
|
||||
const options = qs.parse(location.search, { ignoreQueryPrefix: true });
|
||||
return {
|
||||
options,
|
||||
logo,
|
||||
bar: getBar(),
|
||||
pie,
|
||||
polar,
|
||||
@ -444,7 +482,7 @@ export default {
|
||||
function getAirportCoord(idx) {
|
||||
return [data.airports[idx][3], data.airports[idx][4]];
|
||||
}
|
||||
const routes = data.routes.map(function(airline) {
|
||||
const routes = data.routes.map(airline => {
|
||||
return [getAirportCoord(airline[1]), getAirportCoord(airline[2])];
|
||||
});
|
||||
|
||||
@ -533,7 +571,11 @@ export default {
|
||||
watch: {
|
||||
connected: {
|
||||
handler(value) {
|
||||
echarts[value ? "connect" : "disconnect"]("radiance");
|
||||
if (value) {
|
||||
connect("radiance");
|
||||
} else {
|
||||
disconnect("radiance");
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
@ -557,6 +599,9 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.startActions();
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.stopActions();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -680,7 +725,6 @@ select {
|
||||
font: inherit;
|
||||
padding: 0 0.5em;
|
||||
transition: opacity 0.3s;
|
||||
-webkit-appearance: none;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:focus {
|
||||
@ -851,10 +895,6 @@ figure {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
select {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
display: none;
|
||||
|
||||
|
||||
@ -12,27 +12,27 @@ export default function getData() {
|
||||
source: [
|
||||
{
|
||||
Product: "Matcha Latte",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
},
|
||||
{
|
||||
Product: "Milk Tea",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
},
|
||||
{
|
||||
Product: "Cheese Cocoa",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
},
|
||||
{
|
||||
Product: "Walnut Brownie",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -446,7 +446,7 @@ export default {
|
||||
data: convertData(data),
|
||||
symbolSize: val => val[2] / 10,
|
||||
tooltip: {
|
||||
formatter: function(val) {
|
||||
formatter: function (val) {
|
||||
return val.name + ": " + val.value[2];
|
||||
}
|
||||
},
|
||||
@ -468,7 +468,7 @@ export default {
|
||||
scale: true
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function(val) {
|
||||
formatter: function (val) {
|
||||
return val.name + ": " + val.value[2];
|
||||
}
|
||||
},
|
||||
|
||||
5
src/demo/jsconfig.json
Normal file
5
src/demo/jsconfig.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"files": [
|
||||
"./Demo.vue"
|
||||
],
|
||||
}
|
||||
58
src/index.vue2.d.ts
vendored
58
src/index.vue2.d.ts
vendored
@ -1,9 +1,63 @@
|
||||
/* eslint-disable @typescript-eslint/ban-types */
|
||||
import type { Ref, DefineComponent } from "vue-demi";
|
||||
import type {
|
||||
Option,
|
||||
InitOptions,
|
||||
UpdateOptions,
|
||||
EChartsType,
|
||||
Emits
|
||||
} from "./types";
|
||||
|
||||
declare const LOADING_OPTIONS_KEY = "ecLoadingOptions";
|
||||
declare const THEME_KEY = "ecTheme";
|
||||
declare const INIT_OPTIONS_KEY = "ecInitOptions";
|
||||
declare const UPDATE_OPTIONS_KEY = "ecUpdateOptions";
|
||||
|
||||
declare const _default: any;
|
||||
declare type ChartProps = {
|
||||
loading?: boolean;
|
||||
loadingOptions?: Record<string, unknown>;
|
||||
autoresize?: boolean;
|
||||
option?: Option;
|
||||
theme?: string | Record<string, unknown>;
|
||||
initOptions?: InitOptions;
|
||||
updateOptions?: UpdateOptions;
|
||||
group?: string;
|
||||
manualUpdate?: boolean;
|
||||
};
|
||||
|
||||
export default _default;
|
||||
type MethodNames =
|
||||
| "getWidth"
|
||||
| "getHeight"
|
||||
| "getDom"
|
||||
| "getOption"
|
||||
| "resize"
|
||||
| "dispatchAction"
|
||||
| "convertToPixel"
|
||||
| "convertFromPixel"
|
||||
| "containPixel"
|
||||
| "getDataURL"
|
||||
| "getConnectedDataURL"
|
||||
| "appendData"
|
||||
| "clear"
|
||||
| "isDisposed"
|
||||
| "dispose"
|
||||
| "setOption";
|
||||
|
||||
declare type ChartMethods = Pick<EChartsType, MethodNames>;
|
||||
|
||||
declare const Chart: DefineComponent<
|
||||
ChartProps,
|
||||
{
|
||||
root: Ref<HTMLElement | undefined>;
|
||||
chart: Ref<EChartsType | undefined>;
|
||||
},
|
||||
{},
|
||||
{},
|
||||
ChartMethods,
|
||||
{},
|
||||
{},
|
||||
Emits
|
||||
>;
|
||||
|
||||
export default Chart;
|
||||
export { INIT_OPTIONS_KEY, LOADING_OPTIONS_KEY, THEME_KEY, UPDATE_OPTIONS_KEY };
|
||||
|
||||
@ -1 +1 @@
|
||||
x-vue-echarts{display:block;width:100%;height:100%}
|
||||
x-vue-echarts{display:block;width:100%;height:100%;min-width:0}
|
||||
|
||||
91
src/types.ts
91
src/types.ts
@ -1,28 +1,83 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { init } from "echarts/core";
|
||||
import { Ref } from "vue";
|
||||
import { init, type SetOptionOpts } from "echarts/core";
|
||||
import type { Ref } from "vue";
|
||||
|
||||
export type Injection<T> = T | null | Ref<T | null> | { value: T | null };
|
||||
|
||||
type InitType = typeof init;
|
||||
export type InitParameters = Parameters<InitType>;
|
||||
export type Theme = NonNullable<InitParameters[1]>;
|
||||
export type ThemeInjection = Theme | null | Ref<Theme | null>;
|
||||
export type ThemeInjection = Injection<Theme>;
|
||||
export type InitOptions = NonNullable<InitParameters[2]>;
|
||||
export type InitOptionsInjection = InitOptions | null | Ref<InitOptions | null>;
|
||||
|
||||
export type InitOptionsInjection = Injection<InitOptions>;
|
||||
|
||||
export type UpdateOptions = SetOptionOpts;
|
||||
export type UpdateOptionsInjection = Injection<UpdateOptions>;
|
||||
|
||||
export type EChartsType = ReturnType<InitType>;
|
||||
type ZRenderType = ReturnType<EChartsType["getZr"]>;
|
||||
export type EventTarget = EChartsType | ZRenderType;
|
||||
type SetOptionType = EChartsType["setOption"];
|
||||
export type Option = Parameters<SetOptionType>[0];
|
||||
|
||||
// TODO: Wait for apache/echarts#14289 to ship in v5.1,
|
||||
// so that we can use SetOptionOpts directly
|
||||
export interface UpdateOptions {
|
||||
notMerge?: boolean;
|
||||
lazyUpdate?: boolean;
|
||||
silent?: boolean;
|
||||
replaceMerge?: any;
|
||||
transition?: any;
|
||||
}
|
||||
export type UpdateOptionsInjection =
|
||||
| UpdateOptions
|
||||
| null
|
||||
| Ref<UpdateOptions | null>;
|
||||
type EChartsEventName =
|
||||
| "click"
|
||||
| "dblclick"
|
||||
| "mousedown"
|
||||
| "mousemove"
|
||||
| "mouseup"
|
||||
| "mouseover"
|
||||
| "mouseout"
|
||||
| "globalout"
|
||||
| "contextmenu"
|
||||
| "highlight"
|
||||
| "downplay"
|
||||
| "selectchanged"
|
||||
| "legendselectchanged"
|
||||
| "legendselected"
|
||||
| "legendunselected"
|
||||
| "legendselectall"
|
||||
| "legendinverseselect"
|
||||
| "legendscroll"
|
||||
| "datazoom"
|
||||
| "datarangeselected"
|
||||
| "graphroam"
|
||||
| "georoam"
|
||||
| "treeroam"
|
||||
| "timelinechanged"
|
||||
| "timelineplaychanged"
|
||||
| "restore"
|
||||
| "dataviewchanged"
|
||||
| "magictypechanged"
|
||||
| "geoselectchanged"
|
||||
| "geoselected"
|
||||
| "geounselected"
|
||||
| "axisareaselected"
|
||||
| "brush"
|
||||
| "brushEnd"
|
||||
| "brushselected"
|
||||
| "globalcursortaken"
|
||||
| "rendered"
|
||||
| "finished";
|
||||
type ZRenderEventName =
|
||||
| "click"
|
||||
| "dblclick"
|
||||
| "mousewheel"
|
||||
| "mouseout"
|
||||
| "mouseover"
|
||||
| "mouseup"
|
||||
| "mousedown"
|
||||
| "mousemove"
|
||||
| "contextmenu"
|
||||
| "drag"
|
||||
| "dragstart"
|
||||
| "dragend"
|
||||
| "dragenter"
|
||||
| "dragleave"
|
||||
| "dragover"
|
||||
| "drop"
|
||||
| "globalout";
|
||||
type EventName = EChartsEventName | `zr:${ZRenderEventName}`;
|
||||
export type Emits = {
|
||||
[key in EventName]: null;
|
||||
};
|
||||
|
||||
20
src/utils.ts
20
src/utils.ts
@ -1,3 +1,6 @@
|
||||
import { unref } from "vue-demi";
|
||||
import type { Injection } from "./types";
|
||||
|
||||
type Attrs = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[key: string]: any;
|
||||
@ -6,9 +9,9 @@ type Attrs = {
|
||||
// Copied from
|
||||
// https://github.com/vuejs/vue-next/blob/5a7a1b8293822219283d6e267496bec02234b0bc/packages/shared/src/index.ts#L40-L41
|
||||
const onRE = /^on[^a-z]/;
|
||||
export const isOn = (key: string) => onRE.test(key);
|
||||
export const isOn = (key: string): boolean => onRE.test(key);
|
||||
|
||||
export function omitOn(attrs: Attrs) {
|
||||
export function omitOn(attrs: Attrs): Attrs {
|
||||
const result: Attrs = {};
|
||||
for (const key in attrs) {
|
||||
if (!isOn(key)) {
|
||||
@ -18,3 +21,16 @@ export function omitOn(attrs: Attrs) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function unwrapInjected<T, V>(
|
||||
injection: Injection<T>,
|
||||
defaultValue: V
|
||||
): T | V {
|
||||
const value = unref(injection);
|
||||
|
||||
if (value && typeof value === "object" && "value" in value) {
|
||||
return value.value || defaultValue;
|
||||
}
|
||||
|
||||
return value || defaultValue;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
{
|
||||
"allowJs": true,
|
||||
"compilerOptions": {
|
||||
"target": "ES5",
|
||||
"module": "ESNext",
|
||||
@ -12,7 +13,6 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": ["webpack-env"],
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable", "ScriptHost"]
|
||||
},
|
||||
"include": [
|
||||
|
||||
@ -6,14 +6,20 @@ module.exports = {
|
||||
css: {
|
||||
loaderOptions: {
|
||||
postcss: {
|
||||
plugins: [nested()]
|
||||
postcssOptions: {
|
||||
plugins: [nested()]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
chainWebpack: config => {
|
||||
config
|
||||
.entry("app")
|
||||
config.entry("app").clear().add("./src/demo/main.ts");
|
||||
|
||||
config.module
|
||||
.rule("svg")
|
||||
.clear()
|
||||
.add("./src/demo/main.ts");
|
||||
.test(/\.svg$/)
|
||||
.use("raw-loader")
|
||||
.loader("raw-loader");
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user