mirror of
https://github.com/ecomfe/vue-echarts.git
synced 2025-10-28 23:48:21 +08:00
feat: vue-echarts-next first version
This commit is contained in:
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
dist
|
||||||
3049
package-lock.json
generated
3049
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -1,17 +1,22 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-echarts-next",
|
"name": "vue-echarts-next",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build:demo": "vue-cli-service build",
|
||||||
|
"build": "rollup -c rollup.config.js",
|
||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
|
"main": "dist/index.cjs.min.js",
|
||||||
|
"module": "dist/index.esm.min.js",
|
||||||
|
"unpkg": "dist/index.umd.min.js",
|
||||||
|
"jsdelivr": "dist/index.umd.min.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"vue": "^3.0.0"
|
"resize-detector": "^0.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-node-resolve": "^11.1.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||||
"@typescript-eslint/parser": "^2.33.0",
|
"@typescript-eslint/parser": "^2.33.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
@ -19,12 +24,24 @@
|
|||||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.0",
|
||||||
"@vue/compiler-sfc": "^3.0.0",
|
"@vue/compiler-sfc": "^3.0.0",
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
"@vue/eslint-config-prettier": "^6.0.0",
|
"@vue/eslint-config-prettier": "^6.0.0",
|
||||||
"@vue/eslint-config-typescript": "^5.0.2",
|
"@vue/eslint-config-typescript": "^5.0.2",
|
||||||
|
"echarts": "^5.0.2",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-prettier": "^3.1.3",
|
"eslint-plugin-prettier": "^3.1.3",
|
||||||
"eslint-plugin-vue": "^7.0.0-0",
|
"eslint-plugin-vue": "^7.0.0-0",
|
||||||
|
"postcss": "^8.2.5",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"typescript": "~3.9.3"
|
"rollup": "^2.38.5",
|
||||||
|
"rollup-plugin-postcss": "^4.0.0",
|
||||||
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
|
"rollup-plugin-typescript2": "^0.29.0",
|
||||||
|
"typescript": "^4.1.3",
|
||||||
|
"vue": "npm:vue@^3.0.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"echarts": "^5.0.2",
|
||||||
|
"vue": "^2.6.11 || ^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
98
rollup.config.js
Normal file
98
rollup.config.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import typescript from "rollup-plugin-typescript2";
|
||||||
|
import { terser } from "rollup-plugin-terser";
|
||||||
|
import postcss from "rollup-plugin-postcss";
|
||||||
|
import resolve from "@rollup/plugin-node-resolve";
|
||||||
|
|
||||||
|
/** @type {import('rollup').RollupOptions} */
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
plugins: [
|
||||||
|
typescript({
|
||||||
|
useTsconfigDeclarationDir: true
|
||||||
|
}),
|
||||||
|
postcss()
|
||||||
|
],
|
||||||
|
external: ["vue", "echarts/core", "resize-detector"],
|
||||||
|
input: "src/index.ts",
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
file: "dist/index.esm.js",
|
||||||
|
format: "es",
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: "dist/index.esm.min.js",
|
||||||
|
format: "es",
|
||||||
|
sourcemap: true,
|
||||||
|
plugins: [
|
||||||
|
terser({
|
||||||
|
format: {
|
||||||
|
comments: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: "dist/index.cjs.js",
|
||||||
|
format: "cjs",
|
||||||
|
exports: "default",
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: "dist/index.cjs.min.js",
|
||||||
|
format: "cjs",
|
||||||
|
exports: "default",
|
||||||
|
sourcemap: true,
|
||||||
|
plugins: [
|
||||||
|
terser({
|
||||||
|
format: {
|
||||||
|
comments: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugins: [
|
||||||
|
resolve(),
|
||||||
|
typescript({
|
||||||
|
useTsconfigDeclarationDir: true
|
||||||
|
}),
|
||||||
|
postcss()
|
||||||
|
],
|
||||||
|
external: ["vue", "echarts/core"],
|
||||||
|
input: "src/all.ts",
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
file: "dist/index.umd.js",
|
||||||
|
format: "umd",
|
||||||
|
name: "VueECharts",
|
||||||
|
sourcemap: true,
|
||||||
|
globals: {
|
||||||
|
vue: "Vue",
|
||||||
|
"echarts/core": "echarts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: "dist/index.umd.min.js",
|
||||||
|
format: "umd",
|
||||||
|
name: "VueECharts",
|
||||||
|
sourcemap: true,
|
||||||
|
globals: {
|
||||||
|
vue: "Vue",
|
||||||
|
"echarts/core": "echarts"
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
terser({
|
||||||
|
format: {
|
||||||
|
comments: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export default options;
|
||||||
0
src/shims-vue.d.ts → shims-vue.d.ts
vendored
0
src/shims-vue.d.ts → shims-vue.d.ts
vendored
27
src/App.vue
27
src/App.vue
@ -1,27 +0,0 @@
|
|||||||
<template>
|
|
||||||
<img alt="Vue logo" src="./assets/logo.png" />
|
|
||||||
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
import HelloWorld from "./components/HelloWorld.vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "App",
|
|
||||||
components: {
|
|
||||||
HelloWorld
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
#app {
|
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #2c3e50;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
195
src/ECharts.ts
Normal file
195
src/ECharts.ts
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import {
|
||||||
|
defineComponent,
|
||||||
|
ref,
|
||||||
|
shallowRef,
|
||||||
|
toRefs,
|
||||||
|
watch,
|
||||||
|
computed,
|
||||||
|
inject,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted,
|
||||||
|
h,
|
||||||
|
PropType
|
||||||
|
} from "vue";
|
||||||
|
import { init as initChart } from "echarts/core";
|
||||||
|
import { EChartsType, OptionType } from "@/types";
|
||||||
|
import {
|
||||||
|
usePublicAPI,
|
||||||
|
useAutoresize,
|
||||||
|
autoresizeProps,
|
||||||
|
useLoading,
|
||||||
|
loadingProps
|
||||||
|
} from "./composables";
|
||||||
|
import "./style.css";
|
||||||
|
|
||||||
|
type InitParameters = Parameters<typeof initChart>;
|
||||||
|
type ThemeParameter = InitParameters[1];
|
||||||
|
type InitOptsParameter = InitParameters[2];
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "echarts",
|
||||||
|
props: {
|
||||||
|
options: Object as PropType<OptionType>,
|
||||||
|
theme: {
|
||||||
|
type: [Object, String] as PropType<ThemeParameter>
|
||||||
|
},
|
||||||
|
initOptions: Object as PropType<InitOptsParameter>,
|
||||||
|
group: String,
|
||||||
|
manualUpdate: Boolean,
|
||||||
|
...autoresizeProps,
|
||||||
|
...loadingProps
|
||||||
|
},
|
||||||
|
setup(props, { attrs }) {
|
||||||
|
const defaultInitOptions = inject(
|
||||||
|
"echartsInitOptions",
|
||||||
|
{}
|
||||||
|
) as InitOptsParameter;
|
||||||
|
const root = ref<HTMLElement>();
|
||||||
|
const chart = shallowRef<EChartsType>();
|
||||||
|
const manualOptions = shallowRef<OptionType>();
|
||||||
|
const realOptions = computed(
|
||||||
|
() => manualOptions.value || props.options || Object.create(null)
|
||||||
|
);
|
||||||
|
|
||||||
|
function init(options?: OptionType) {
|
||||||
|
if (chart.value || !root.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = (chart.value = initChart(
|
||||||
|
root.value,
|
||||||
|
props.theme,
|
||||||
|
props.initOptions || defaultInitOptions
|
||||||
|
));
|
||||||
|
|
||||||
|
if (props.group) {
|
||||||
|
instance.group = props.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(attrs)
|
||||||
|
.filter(key => key.indexOf(`on`) === 0)
|
||||||
|
.forEach(key => {
|
||||||
|
const handler = attrs[key] as any;
|
||||||
|
|
||||||
|
if (!handler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.indexOf("onZr:") === 0) {
|
||||||
|
instance.getZr().on(key.slice(5).toLowerCase(), handler);
|
||||||
|
} else {
|
||||||
|
instance.on(key.slice(2).toLowerCase(), handler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
instance.setOption(options || realOptions.value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeOptions(options: OptionType, ...rest: any[]) {
|
||||||
|
if (props.manualUpdate) {
|
||||||
|
manualOptions.value = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chart.value) {
|
||||||
|
init(options);
|
||||||
|
} else {
|
||||||
|
chart.value.setOption(options, ...rest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
if (chart.value) {
|
||||||
|
chart.value.dispose();
|
||||||
|
chart.value = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
theme,
|
||||||
|
initOptions,
|
||||||
|
group,
|
||||||
|
autoresize,
|
||||||
|
manualUpdate,
|
||||||
|
loading,
|
||||||
|
loadingOptions
|
||||||
|
} = toRefs(props);
|
||||||
|
let unwatchOptions: (() => void) | null = null;
|
||||||
|
watch(
|
||||||
|
manualUpdate,
|
||||||
|
manualUpdate => {
|
||||||
|
if (typeof unwatchOptions === "function") {
|
||||||
|
unwatchOptions();
|
||||||
|
unwatchOptions = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!manualUpdate) {
|
||||||
|
unwatchOptions = watch(
|
||||||
|
() => props.options,
|
||||||
|
(val, oldVal) => {
|
||||||
|
if (!val) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!chart.value) {
|
||||||
|
init();
|
||||||
|
} else {
|
||||||
|
// mutating `options` will lead to merging
|
||||||
|
// replacing it with new reference will lead to not merging
|
||||||
|
// eg.
|
||||||
|
// `this.options = Object.assign({}, this.options, { ... })`
|
||||||
|
// will trigger `this.chart.setOption(val, true)
|
||||||
|
// `this.options.title.text = 'Trends'`
|
||||||
|
// will trigger `this.chart.setOption(val, false)`
|
||||||
|
chart.value.setOption(val, val !== oldVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch([theme, initOptions], () => {
|
||||||
|
cleanup();
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => group,
|
||||||
|
group => {
|
||||||
|
if (group && group.value && chart.value) {
|
||||||
|
chart.value.group = group.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const publicApi = usePublicAPI(chart, init);
|
||||||
|
|
||||||
|
useLoading(chart, loading, loadingOptions);
|
||||||
|
|
||||||
|
useAutoresize(chart, autoresize, root, realOptions);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.options) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(cleanup);
|
||||||
|
|
||||||
|
return {
|
||||||
|
root,
|
||||||
|
mergeOptions,
|
||||||
|
...publicApi
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return h("div", {
|
||||||
|
ref: "root",
|
||||||
|
class: "echarts"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
3
src/all.ts
Normal file
3
src/all.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import "echarts";
|
||||||
|
|
||||||
|
export { default } from "./ECharts";
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
@ -1,124 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br />
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
|
||||||
>vue-cli documentation</a
|
|
||||||
>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>babel</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>typescript</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>eslint</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
|
||||||
>Forum</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
|
||||||
>Community Chat</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
|
||||||
>Twitter</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
|
||||||
>vue-router</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>vue-devtools</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
|
||||||
>vue-loader</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
href="https://github.com/vuejs/awesome-vue"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
>awesome-vue</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "HelloWorld",
|
|
||||||
props: {
|
|
||||||
msg: String
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped>
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
54
src/composables/api.ts
Normal file
54
src/composables/api.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import { Ref } from "vue";
|
||||||
|
import { EChartsType, OptionType } from "@/types";
|
||||||
|
|
||||||
|
const METHOD_NAMES = [
|
||||||
|
"getWidth",
|
||||||
|
"getHeight",
|
||||||
|
"getDom",
|
||||||
|
"getOption",
|
||||||
|
"resize",
|
||||||
|
"dispatchAction",
|
||||||
|
"convertToPixel",
|
||||||
|
"convertFromPixel",
|
||||||
|
"getDataURL",
|
||||||
|
"getConnectedDataURL",
|
||||||
|
"appendData",
|
||||||
|
"clear",
|
||||||
|
"isDisposed",
|
||||||
|
"dispose"
|
||||||
|
] as const;
|
||||||
|
type MethodName = typeof METHOD_NAMES[number];
|
||||||
|
|
||||||
|
type PublicMethods = Pick<EChartsType, MethodName>;
|
||||||
|
|
||||||
|
export function usePublicAPI(
|
||||||
|
chart: Ref<EChartsType | undefined>,
|
||||||
|
init: (options?: OptionType) => void
|
||||||
|
) {
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
return (chart.value[name] as any).apply(chart.value, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePublicMethods(): PublicMethods {
|
||||||
|
const methods = Object.create(null);
|
||||||
|
METHOD_NAMES.forEach(name => {
|
||||||
|
methods[name] = makePublicMethod(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
return methods as PublicMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
return makePublicMethods();
|
||||||
|
}
|
||||||
50
src/composables/autoresize.ts
Normal file
50
src/composables/autoresize.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { Ref, watch } from "vue";
|
||||||
|
import { addListener, removeListener, ResizeCallback } from "resize-detector";
|
||||||
|
import { EChartsType, OptionsType } from "@/types";
|
||||||
|
|
||||||
|
export function useAutoresize(
|
||||||
|
chart: Ref<EChartsType | undefined>,
|
||||||
|
autoresize: Ref<boolean>,
|
||||||
|
root: Ref<HTMLElement | undefined>,
|
||||||
|
options: Ref<OptionsType>
|
||||||
|
): 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 = () => {
|
||||||
|
if (lastArea === 0) {
|
||||||
|
chart.setOption(Object.create(null), true);
|
||||||
|
chart.resize();
|
||||||
|
chart.setOption(options.value, true);
|
||||||
|
} else {
|
||||||
|
chart.resize();
|
||||||
|
}
|
||||||
|
lastArea = getArea();
|
||||||
|
};
|
||||||
|
|
||||||
|
addListener(root, resizeListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup(() => {
|
||||||
|
if (resizeListener && root) {
|
||||||
|
lastArea = 0;
|
||||||
|
removeListener(root, resizeListener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const autoresizeProps = {
|
||||||
|
autoresize: Boolean
|
||||||
|
};
|
||||||
3
src/composables/index.ts
Normal file
3
src/composables/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./api";
|
||||||
|
export * from "./autoresize";
|
||||||
|
export * from "./loading";
|
||||||
41
src/composables/loading.ts
Normal file
41
src/composables/loading.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { Ref, PropType, watchEffect } from "vue";
|
||||||
|
import { EChartsType } from "@/types";
|
||||||
|
|
||||||
|
export interface LoadingOptions {
|
||||||
|
text?: string;
|
||||||
|
color?: string;
|
||||||
|
textColor?: string;
|
||||||
|
maskColor?: string;
|
||||||
|
zlevel?: number;
|
||||||
|
fontSize?: number;
|
||||||
|
showSpinner?: boolean;
|
||||||
|
spinnerRadius?: number;
|
||||||
|
lineWidth?: number;
|
||||||
|
fontWeight?: string | number;
|
||||||
|
fontStyle?: string;
|
||||||
|
fontFamily?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useLoading(
|
||||||
|
chart: Ref<EChartsType | undefined>,
|
||||||
|
loading: Ref<boolean>,
|
||||||
|
loadingOptions?: Ref<LoadingOptions | undefined>
|
||||||
|
): void {
|
||||||
|
watchEffect(() => {
|
||||||
|
const instance = chart.value;
|
||||||
|
if (!instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading.value) {
|
||||||
|
instance.showLoading(loadingOptions?.value);
|
||||||
|
} else {
|
||||||
|
instance.hideLoading();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const loadingProps = {
|
||||||
|
loading: Boolean,
|
||||||
|
loadingOptions: Object as PropType<LoadingOptions>
|
||||||
|
};
|
||||||
154
src/demo/App.vue
Normal file
154
src/demo/App.vue
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
<template>
|
||||||
|
<article>
|
||||||
|
<div class="settings">
|
||||||
|
<label><input type="checkbox" v-model="autoresize" /> Autoresize</label>
|
||||||
|
<label
|
||||||
|
><input type="checkbox" v-model="defaultTheme" /> Default theme</label
|
||||||
|
>
|
||||||
|
<label><input type="checkbox" v-model="loading" /> Loading</label>
|
||||||
|
<label><input type="checkbox" v-model="useSvg" /> Use SVG</label>
|
||||||
|
<label><input type="checkbox" v-model="useRef" /> Use ref data</label>
|
||||||
|
<button @click="mutate" :disabled="useRef">Mutate data</button>
|
||||||
|
<button @click="set" :disabled="!useRef">Set data</button>
|
||||||
|
<button @click="mutateLoadingOptions" :disabled="!loading">
|
||||||
|
Mutate loading options
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<v-chart
|
||||||
|
style="width: 100%; height: 400px"
|
||||||
|
ref="foo"
|
||||||
|
:autoresize="autoresize"
|
||||||
|
:options="realOptions"
|
||||||
|
:loading="loading"
|
||||||
|
:loading-options="loadingOptions"
|
||||||
|
:theme="defaultTheme ? null : 'dark'"
|
||||||
|
:init-options="initOptions"
|
||||||
|
@click="log('echarts')"
|
||||||
|
@zr:click="log('zr')"
|
||||||
|
/>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, reactive, ref } from "vue";
|
||||||
|
import VChart from "../ECharts";
|
||||||
|
import * as echarts from "echarts/core";
|
||||||
|
import { GridComponent } from "echarts/components";
|
||||||
|
import { LineChart } from "echarts/charts";
|
||||||
|
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
|
||||||
|
|
||||||
|
echarts.use([GridComponent, LineChart, CanvasRenderer, SVGRenderer]);
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "App",
|
||||||
|
components: {
|
||||||
|
VChart
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const foo = ref();
|
||||||
|
const options = reactive({
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value"
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [150, 230, 224, 218, 135, 147, 260],
|
||||||
|
type: "line"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const optionsRef = ref({
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value"
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [233, 128, 184, 302, 208, 287, 212],
|
||||||
|
type: "line"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadingOptions = reactive({
|
||||||
|
text: "正在加载..."
|
||||||
|
});
|
||||||
|
|
||||||
|
const autoresize = ref<boolean>(true);
|
||||||
|
const defaultTheme = ref<boolean>(true);
|
||||||
|
const useSvg = ref<boolean>(false);
|
||||||
|
const useRef = ref<boolean>(false);
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
const initOptions = computed(() => ({
|
||||||
|
renderer: useSvg.value ? "svg" : "canvas"
|
||||||
|
}));
|
||||||
|
const realOptions = computed(() =>
|
||||||
|
useRef.value ? optionsRef.value : options
|
||||||
|
);
|
||||||
|
|
||||||
|
function mutate() {
|
||||||
|
options.series[0].data = [150, 230, 224, 218, 135, 147, 260].map(
|
||||||
|
val => val + Math.round(50 * Math.random())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set() {
|
||||||
|
optionsRef.value = {
|
||||||
|
xAxis: {
|
||||||
|
type: "category",
|
||||||
|
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: "value"
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [
|
||||||
|
233 + Math.round(50 * Math.random()),
|
||||||
|
128 + Math.round(50 * Math.random()),
|
||||||
|
184 + Math.round(50 * Math.random()),
|
||||||
|
302 + Math.round(50 * Math.random()),
|
||||||
|
208 + Math.round(50 * Math.random()),
|
||||||
|
287 + Math.round(50 * Math.random()),
|
||||||
|
212 + Math.round(50 * Math.random())
|
||||||
|
],
|
||||||
|
type: "line"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mutateLoadingOptions() {
|
||||||
|
loadingOptions.text += ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function log(...args: any[]) {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
realOptions,
|
||||||
|
autoresize,
|
||||||
|
defaultTheme,
|
||||||
|
useSvg,
|
||||||
|
useRef,
|
||||||
|
initOptions,
|
||||||
|
mutate,
|
||||||
|
set,
|
||||||
|
loading,
|
||||||
|
loadingOptions,
|
||||||
|
mutateLoadingOptions,
|
||||||
|
foo,
|
||||||
|
log
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
1
src/index.ts
Normal file
1
src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from "./ECharts";
|
||||||
4
src/style.css
Normal file
4
src/style.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.echarts {
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
5
src/types.ts
Normal file
5
src/types.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { init } from "echarts/core";
|
||||||
|
|
||||||
|
export type EChartsType = ReturnType<typeof init>;
|
||||||
|
type SetOptionType = EChartsType["setOption"];
|
||||||
|
export type OptionType = Parameters<SetOptionType>[0];
|
||||||
@ -1,39 +1,32 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
"target": "ES5",
|
||||||
"module": "esnext",
|
"module": "ESNext",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
"removeComments": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"types": [
|
"types": ["webpack-env"],
|
||||||
"webpack-env"
|
|
||||||
],
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": ["src/*"]
|
||||||
"src/*"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"lib": [
|
"lib": ["ESNext", "DOM", "DOM.Iterable", "ScriptHost"],
|
||||||
"esnext",
|
// "declaration": true,
|
||||||
"dom",
|
// "declarationDir": "dist"
|
||||||
"dom.iterable",
|
|
||||||
"scripthost"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.tsx",
|
"src/**/*.tsx",
|
||||||
"src/**/*.vue",
|
"src/**/*.vue",
|
||||||
"tests/**/*.ts",
|
"shims-vue.d.ts",
|
||||||
"tests/**/*.tsx"
|
"src/demo/**/*.ts",
|
||||||
|
"src/demo/**/*.vue"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": ["node_modules"]
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
10
vue.config.js
Normal file
10
vue.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
outputDir: "demo",
|
||||||
|
transpileDependencies: ["resize-detector"],
|
||||||
|
chainWebpack: config => {
|
||||||
|
config
|
||||||
|
.entry("app")
|
||||||
|
.clear()
|
||||||
|
.add("./src/demo/main.ts");
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user