Skip to content
@niu-tools/vue3
useEchart
<script setup lang="ts">
import { useEChart } from '@niu-tools/vue3'
import { useResizeObserver } from '@vueuse/core'
import { onMounted, ref } from 'vue'

const data: number[][] = []

for (let i = 0; i <= 100; i++) {
    let theta = (i / 100) * 360
    let r = 5 * (1 + Math.sin((theta / 180) * Math.PI))
    data.push([r, theta])
}

function getOptions(data) {
    return {
        title: {
            text: 'Two Value-Axes in Polar',
        },
        legend: {
            data: ['line'],
        },
        polar: {},
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'cross',
            },
        },
        angleAxis: {
            type: 'value',
            startAngle: 0,
        },
        radiusAxis: {},
        series: [
            {
                coordinateSystem: 'polar',
                name: 'line',
                type: 'line',
                data: data,
            },
        ],
    }
}

function handleClick(num: number) {
    const data: number[][] = []

    for (let i = 0; i <= num; i++) {
        let theta = (i / 100) * 360
        let r = 5 * (1 + Math.sin((theta / 180) * Math.PI))
        data.push([r, theta])
    }
    setOption(getOptions(data))
}

const targetEl = ref<HTMLElement | null>(null)
const { init, clear, dispose, resize, setOption } = useEChart({
    el: targetEl,
    option: getOptions(data),
})

onMounted(() => {
    useResizeObserver(targetEl, () => {
        resize()
    })
})
</script>

<template>
    <div>
        <n-space>
            <n-button @click="handleClick(50)">50数据</n-button>
            <n-button @click="handleClick(100)">100数据</n-button>
            <n-button @click="clear">清除图表</n-button>
            <n-button @click="dispose">销毁图表</n-button>
            <n-button @click="init">初始化图表</n-button>
        </n-space>
        <div
            style="height: 500px; resize: horizontal; overflow: auto"
            ref="targetEl"
        ></div>
    </div>
</template>
<script setup lang="ts">
import { useEChart } from '@niu-tools/vue3'
import { useResizeObserver } from '@vueuse/core'
import { onMounted, ref } from 'vue'

const data: number[][] = []

for (let i = 0; i <= 100; i++) {
    let theta = (i / 100) * 360
    let r = 5 * (1 + Math.sin((theta / 180) * Math.PI))
    data.push([r, theta])
}

function getOptions(data) {
    return {
        title: {
            text: 'Two Value-Axes in Polar',
        },
        legend: {
            data: ['line'],
        },
        polar: {},
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'cross',
            },
        },
        angleAxis: {
            type: 'value',
            startAngle: 0,
        },
        radiusAxis: {},
        series: [
            {
                coordinateSystem: 'polar',
                name: 'line',
                type: 'line',
                data: data,
            },
        ],
    }
}

function handleClick(num: number) {
    const data: number[][] = []

    for (let i = 0; i <= num; i++) {
        let theta = (i / 100) * 360
        let r = 5 * (1 + Math.sin((theta / 180) * Math.PI))
        data.push([r, theta])
    }
    setOption(getOptions(data))
}

const targetEl = ref<HTMLElement | null>(null)
const { init, clear, dispose, resize, setOption } = useEChart({
    el: targetEl,
    option: getOptions(data),
})

onMounted(() => {
    useResizeObserver(targetEl, () => {
        resize()
    })
})
</script>

<template>
    <div>
        <n-space>
            <n-button @click="handleClick(50)">50数据</n-button>
            <n-button @click="handleClick(100)">100数据</n-button>
            <n-button @click="clear">清除图表</n-button>
            <n-button @click="dispose">销毁图表</n-button>
            <n-button @click="init">初始化图表</n-button>
        </n-space>
        <div
            style="height: 500px; resize: horizontal; overflow: auto"
            ref="targetEl"
        ></div>
    </div>
</template>

源码

查看源码
useEchart/index.ts源码
ts
export * from "./useEchart"
export * from "./useEchart"
useEchart/useEchart.ts源码
ts
import { ref, Ref, unref } from "vue"
import * as echarts from "echarts"
import type { } from "echarts"
import { useEventListener, tryOnMounted, tryOnBeforeUnmount } from "@vueuse/core";

export function useEChart(opts: { el: Ref<HTMLElement | null>; option?: any, cloneNode?: boolean }) {
    const originOption = opts.option ?? {}
    let myChart: ReturnType<typeof echarts.init> | null = null
    let pureEl: Node | undefined
    let curOption = ref(originOption)

    const stop = useEventListener(window, "resize", () => {
        if (!myChart) return
        myChart?.resize()
    })
    function clear() {
        if (!myChart) return
        myChart?.clear()
    }

    function dispose() {
        if (!myChart) return
        if (myChart.isDisposed()) return
        // curOption.value = originOption
        myChart?.dispose()
        if (pureEl) {
            const el = unref(opts.el)
            el?.replaceWith(pureEl)
            opts.el.value = pureEl as any
            pureEl = undefined
        }
        myChart = null
    }

    function resize() {
        myChart?.resize()
    }

    tryOnMounted(init)
    tryOnBeforeUnmount(() => {
        stop()
        dispose()
        myChart = null
        pureEl = undefined
        curOption.value = undefined
    })
    function setOption(option: object | null = null) {
        if (option) curOption.value = option
        myChart && myChart.setOption(curOption.value)
    }
    function init() {
        if (myChart) return
        const el = unref(opts.el)
        if (!el) {
            return
        }
        if (opts.cloneNode) {
            pureEl = el.cloneNode(true)
        }
        myChart = echarts.init(el)
        setOption()
    }
    return {
        init,
        dispose,
        clear,
        resize,
        setOption,
    }
}
import { ref, Ref, unref } from "vue"
import * as echarts from "echarts"
import type { } from "echarts"
import { useEventListener, tryOnMounted, tryOnBeforeUnmount } from "@vueuse/core";

export function useEChart(opts: { el: Ref<HTMLElement | null>; option?: any, cloneNode?: boolean }) {
    const originOption = opts.option ?? {}
    let myChart: ReturnType<typeof echarts.init> | null = null
    let pureEl: Node | undefined
    let curOption = ref(originOption)

    const stop = useEventListener(window, "resize", () => {
        if (!myChart) return
        myChart?.resize()
    })
    function clear() {
        if (!myChart) return
        myChart?.clear()
    }

    function dispose() {
        if (!myChart) return
        if (myChart.isDisposed()) return
        // curOption.value = originOption
        myChart?.dispose()
        if (pureEl) {
            const el = unref(opts.el)
            el?.replaceWith(pureEl)
            opts.el.value = pureEl as any
            pureEl = undefined
        }
        myChart = null
    }

    function resize() {
        myChart?.resize()
    }

    tryOnMounted(init)
    tryOnBeforeUnmount(() => {
        stop()
        dispose()
        myChart = null
        pureEl = undefined
        curOption.value = undefined
    })
    function setOption(option: object | null = null) {
        if (option) curOption.value = option
        myChart && myChart.setOption(curOption.value)
    }
    function init() {
        if (myChart) return
        const el = unref(opts.el)
        if (!el) {
            return
        }
        if (opts.cloneNode) {
            pureEl = el.cloneNode(true)
        }
        myChart = echarts.init(el)
        setOption()
    }
    return {
        init,
        dispose,
        clear,
        resize,
        setOption,
    }
}

Released under the MIT License.