feat: vue-echarts-next first version

This commit is contained in:
Justineo
2021-02-07 16:16:13 +08:00
parent e4ff8e68e0
commit ee12ad9658
22 changed files with 3029 additions and 855 deletions

54
src/composables/api.ts Normal file
View 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();
}

View 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
View File

@ -0,0 +1,3 @@
export * from "./api";
export * from "./autoresize";
export * from "./loading";

View 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>
};