<template> <div class="box" ref="chartRef"></div> </template> <script setup> import * as echarts from "echarts"; import { watch, onMounted, ref, defineProps } from "vue"; let myChart; let chartRef = ref(null); const props = defineProps({ title: { type: String, default: "標題" } }); const data1 = [ { value: 33, name: 'rose 1' }, { value: 33, name: 'rose 2' }, { value: 30, name: 'rose 3' } ] const data2 = [ { value: 30, name: 'ddd 1' }, { value: 28, name: 'ddd 2' }, { value: 26, name: 'ddd 3' }, { value: 24, name: 'ddd 4' }, { value: 22, name: 'ddd 5' }, { value: 20, name: 'ddd 6' }, { value: 18, name: 'ddd 7' }, { value: 16, name: 'ddd 8' } ] let textColor = "white" let markLineData = [] const option = { legend: {}, tooltip: {}, //圖例 legend: { show: false, right: '5%',//靠右 orient: 'vertical',//垂直排列 top: 'center', // 上下居中 align: 'left',//文字在圖例左側 itemGap: 20, //圖例間距 textStyle: { color: textColor } }, series: [ { type: 'pie', radius: "70%", center: ['30%', '50%'], label: { show: true, position: "inside", }, startAngle: 45, // 起始角度 45 clockwise: false, // 逆時針 markLine: { lineStyle: { type: 'solid', color: "#BFBFBF" }, symbol: 'none', data: markLineData }, data: data1 }, { type: 'pie', radius: "40%", center: ['65%', '30%'], encode: { itemName: 'product', value: '2016', }, label: { show: true, position: "inside" }, data: data2 } ] }; // 獲取表標線 對應點座標 function getMarkLineData(percent) { // 1.獲取畫布 width,height let height = myChart.getHeight() let width = myChart.getWidth() //2.根據 series[0].center,獲取配置 轉 數值 let pie1CenterXpercent = convertPercentageStringToDecimal(option.series[0].center[0]) // 圓心1軸座標X百分比 let pie1CenterYpercent = convertPercentageStringToDecimal(option.series[0].center[1]) // 圓心1軸座標Y百分比 let pie2CenterXpercent = convertPercentageStringToDecimal(option.series[1].center[0]) // 圓心2軸座標X百分比 let pie2CenterYpercent = convertPercentageStringToDecimal(option.series[1].center[1]) // 圓心2軸座標Y百分比 let pie1RadiusPercent = convertPercentageStringToDecimal(option.series[0].radius) //圓心1半徑百分比 let pie2RadiusPercent = convertPercentageStringToDecimal(option.series[1].radius) //圓心2半徑百分比 let pie1Radius = height / 2 * pie1RadiusPercent // 圓心半徑 let pie2Radius = height / 2 * pie2RadiusPercent // 圓心半徑 let pie1CenterX = width * pie1CenterXpercent // 圓心1軸座標X let pie1CenterY = height * pie1CenterYpercent // 圓心1軸座標Y let pie2CenterX = width * pie2CenterXpercent // 圓心2軸座標X let pie2CenterY = height * pie2CenterYpercent // 圓心2軸座標Y //3.圓邊上點座標 let line1StartX = pie1CenterX + pie1Radius * Math.cos(45 * 3.14 / 180) // let line1StartX = pie1CenterX + r * cos(ao * 3.14 /180 ) let line1StartY = pie1CenterY - pie1Radius * Math.sin(45 * 3.14 / 180) // let line1StartY = pie1CenterY - r * sin(ao * 3.14 /180 ) let line1EndX = pie2CenterX let line1EndY = pie2CenterY - pie2Radius console.log("線1結束", pie2CenterY, pie2Radius) let ao = 360 * (percent / 100) // 扇形角度 let ao1 = 0 // 用來計算的座標角度 ao1 = (ao <= 45) ? (45 - ao) : (360 - (ao - 45)) if (ao1 < 270 && ao1 > 45) ao1 = 270 // 角度當270用,要不樣式不好看 let line2StartX = pie1CenterX + pie1Radius * Math.cos(ao1 * 3.14 / 180) let line2StartY = pie1CenterY - pie1Radius * Math.sin(ao1 * 3.14 / 180) let line2EndX = pie2CenterX let line2EndY = pie2CenterY + pie2Radius return [ [{ x: line1StartX, y: line1StartY }, { x: line1EndX, // 線1,終點x值 y: line1EndY // 線1,終點y值 }], [{ x: line2StartX, y: line2StartY }, { x: line2EndX,// 線2,終點x值 y: line2EndY // 線2,終點y值 }] ] } // 帶百分號字串轉小數 function convertPercentageStringToDecimal(percentageString) { const percentageValue = parseFloat(percentageString.replace("%", "")) / 100; // console.log("帶百分號字串轉小數",percentageString,percentageValue) return percentageValue; } //透過區塊的佔比(最後一個區塊),計算線條起點和終點 const addOtherData = (arrData) => { let end = arrData.length - 1 let sum = 0; for (let i = 0; i < arrData.length; i++) { let value = arrData[i] ? 0 : Number(arrData[i].value) console.log("item", value) sum += value } let percent = sum ? ((arrData[end].value / sum) * 100).toFixed(2) : 100 console.log("佔比", sum, arrData[end].value, percent) option.series[0].markLine.data = getMarkLineData(percent) console.log(markLineData) } const initChart = () => { addOtherData(data1); myChart.setOption(option); }; watch(props, () => { console.log("表格資料變動"); initChart(); }); onMounted(() => { myChart = echarts.init(chartRef.value); initChart(); }); </script> <style scoped> .box { width: 100%; height: 100%; /* width: 100px; height: 100px; */ } </style>