94 lines
2.2 KiB
Vue
94 lines
2.2 KiB
Vue
<script setup>
|
|
import * as echarts from "echarts";
|
|
import { onMounted, ref, markRaw, nextTick } from "vue";
|
|
import axios from "axios";
|
|
|
|
const props = defineProps({
|
|
option: Object,
|
|
className: String,
|
|
id: String,
|
|
svg: Object,
|
|
getCoordinate: {
|
|
type: Function,
|
|
default: null,
|
|
},
|
|
});
|
|
|
|
let chart = ref(null);
|
|
let dom = ref(null);
|
|
let currentClickPosition = ref([]);
|
|
|
|
async function updateSvg(svg, option) {
|
|
if (!chart.value && dom.value && svg) {
|
|
init();
|
|
} else {
|
|
clear();
|
|
}
|
|
axios.get(svg.path).then(async ({ data }) => {
|
|
echarts.registerMap(svg.full_name, { svg: data });
|
|
await nextTick();
|
|
// 延遲執行以避免在主進程中調用 setOption
|
|
setTimeout(() => {
|
|
if (chart.value && !chart.value.isDisposed()) {
|
|
chart.value.setOption(option);
|
|
}
|
|
}, 0);
|
|
if (props.getCoordinate) {
|
|
chart.value.getZr().on("click", function (params) {
|
|
var pixelPoint = [params.offsetX, params.offsetY];
|
|
var dataPoint = chart.value.convertFromPixel(
|
|
{ geoIndex: 0 },
|
|
pixelPoint
|
|
);
|
|
currentClickPosition.value = dataPoint;
|
|
props.getCoordinate(dataPoint);
|
|
const updatedData = option.series.data
|
|
.filter(
|
|
(point) => !(point.itemStyle && point.itemStyle.color === "#0000FF")
|
|
)
|
|
.concat({
|
|
value: dataPoint, // 當前座標值
|
|
itemStyle: { color: "#0000FF" }, // 設為藍色
|
|
});
|
|
setTimeout(() => {
|
|
if (chart.value && !chart.value.isDisposed()) {
|
|
chart.value.setOption({
|
|
series: {
|
|
data: updatedData,
|
|
},
|
|
});
|
|
}
|
|
}, 0);
|
|
});
|
|
}
|
|
});
|
|
console.log("updateSvg", svg.path);
|
|
}
|
|
|
|
function clear() {
|
|
chart.value.clear();
|
|
}
|
|
|
|
function init() {
|
|
const curChart = echarts.init(dom.value);
|
|
chart.value = markRaw(curChart);
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (!chart.value && dom.value && props.svg) {
|
|
init();
|
|
}
|
|
});
|
|
|
|
defineExpose({
|
|
chart,
|
|
currentClickPosition,
|
|
updateSvg,
|
|
});
|
|
</script>
|
|
<template>
|
|
<div :id="id" class="min-h-[70vh] max-h-fit w-full" ref="dom"></div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped></style>
|