最近做可視化比較多,就常用的圖表類型做了一下總結。
因為做可視化的圖表代碼量非常大,是以會把echarts圖表單獨抽離出來,封裝成一個元件,也可以複用,是以這裡我直接把封裝的元件直接放在這裡,是可以直接拿來用的,根據所需稍作修改即可。
這裡都是用的vue3,其實和vue2差不多,各式各樣的花裡胡哨的圖表無非就是option配置不同,如果使用的是vue2,在寫法上稍作修改即可
vue2、vue3元件封裝模闆連結 echarts圖表元件封裝模闆
1. 精簡圓環圖
<template>
<div :id="id" style="width: 100%; height: 100%"></div>
</template>
<script setup>
import { fontChart } from '@/utils/echartPxToRem'
import * as echarts from "echarts";
import { onMounted, watch, onUnmounted } from "vue";
const props = defineProps({
id: {
type: String,
required: true,
},
text: {
type: String,
default: '這個是頭'
},
value: {
type: Number,
default: 50
},
totalNum: {
type: Number,
default: 150
}
});
watch(
() => props.Value,
(newValue) => {
drawPie()
},
{
deep: true
}
)
let charts = ""; // 這裡不要讓它成為響應式
onMounted(() => {
drawPie();
});
onUnmounted(() => {
window.removeEventListener('resize', selfAdaption)
})
// 初始化echarts
const drawPie = () => {
charts = echarts.init(document.getElementById(props.id));
let option = {
color: ['#414f5b', '#1890ff'],
series: [
{
name: '任務進度',
type: 'pie',
radius: ['65%', '95%'],
avoidLabelOverlap: false,
hoverAnimation: false,
labelLine: {
normal: {
show: false
}
},
data: [{
value: props.totalNum - props.value,
label: {
normal: {
show: false,
}
}
}, { // 資料值
value: props.value,
// 資料項名稱
// name: props.name,
//該資料項是否被選中
selected: false,
// 單個扇區的标簽配置
label: {
// 是顯示标簽
show: true,
position: 'center',
fontSize: fontChart(10),
color: '#fff',
lineHeight: fontChart(15),
formatter: `{b| ${props.text}}` + '\n\n' + `{c| 打鑽進尺}` + '\n\n' + `{a| ${props.value} }` + '\n\n' + `{d| 米}`, // \n換行 兩個就換兩行 a、b、c、d後面不能有空格!
rich: {
a: {
color: '#1890ff',
fontSize: fontChart(35),
fontWeight: 600,
},
b: {
color: '#fff',
fontSize: fontChart(25),
fontWeight: 600,
},
c: {
color: '#fff',
fontSize: fontChart(25),
fontWeight: 600,
},
d: {
color: '#fff',
fontSize: fontChart(25),
fontWeight: 600,
}
}
},
}]
}
]
}
charts.setOption(option)
window.addEventListener('resize', selfAdaption)
};
// 自适應
function selfAdaption() {
if(!charts) return
charts.resize()
drawPie()
}
</script>
2. 經典餅圖 (1)
<template>
<div :id="id" style="width: 100%; height: 100%"></div>
</template>
<script setup>
import { fontChart } from '@/utils/echartPxToRem'
import * as echarts from "echarts";
import { onMounted, watch, onUnmounted } from "vue";
const props = defineProps({
id: {
type: String,
required: true,
},
title: {
type: String,
default: '風險等級統計'
},
colorList: {
type: Array,
default:() => ['#008eea','#fac800','#ff7d00','#f00041']
},
pieData: {
type: Array,
default:() => ([{name:'低風險',value:10},{name:'一般風險',value:6},{name:'較大風險',value:3},{name:'重大風險',value:1}])
},
seriesCenter: {
type: Array,
default:() => ['60%','50%']
}
});
watch(
() => props.pieData,
(newValue) => {
drawPie()
},
{
deep: true
}
)
let charts = ""; // 這裡不要讓它成為響應式
onMounted(() => {
drawPie();
});
onUnmounted(() => {
window.removeEventListener('resize', selfAdaption)
})
// 初始化echarts
const drawPie = () => {
charts = echarts.init(document.getElementById(props.id));
let option = {
title: {
show: false,
left: '50%',
top: 'auto',
text: props.title,
textStyle: {
color:'#868a96',
fontSize:fontChart(13)
}
},
legend: {
textStyle: {
color:'#868a96',
fontSize:fontChart(13)
},
itemWidth: fontChart(20), // 設定寬度
itemHeight: fontChart(10), // 設定高度
x : '5%',
y : 'center',
orient : 'vertical', //horizontal、vertical可選
},
color: props.colorList,
series: [
{
// name: 'Nightingale Chart',
type: 'pie',
center: props.seriesCenter,
label: {
normal: {
show: true,
position:'inner', //outside、inside同inner、center 可選
formatter: '{c}',
fontSize:fontChart(13)
},
},
data: props.pieData
}
]
};
charts.setOption(option)
window.addEventListener('resize', selfAdaption)
};
// 自适應
function selfAdaption() {
if(!charts) return
charts.resize()
drawPie()
}
</script>
3. 經典圖餅圖(2)
<template>
<div :id="id" style="width: 100%; height: 100%"></div>
</template>
<script setup>
import { fontChart } from '@/utils/echartPxToRem'
import * as echarts from "echarts";
import { onMounted, watch, onUnmounted } from "vue";
const props = defineProps({
id: {
type: String,
required:true //聲明這個參數是否必須傳入
},
dataList: {
type: Array,
default: () => ([{ value: 1048, name: 'Search Engine' }, { value: 735, name: 'Direct' }, { value: 580, name: 'Email' }, { value: 484, name: 'Union Ads' }, { value: 300, name: 'Video Ads' }])
}
});
watch(
() => props.dataList,
(newValue) => {
drawPie()
},
{
deep: true
}
)
let charts = ""; // 這裡不要讓它成為響應式
onMounted(() => {
drawPie();
});
onUnmounted(() => {
window.removeEventListener('resize', selfAdaption)
})
// 初始化echarts
const drawPie = () => {
charts = echarts.init(document.getElementById(props.id));
let option = {
title: {
show:true,
text: 'Referer of a Website',
// subtext: 'Fake Data',
left: 'center',
textStyle: {//主标題文本樣式{"fontSize": 18,"fontWeight": "bolder","color": "#333"}
fontSize: fontChart(18),
color:'#fff'
},
subtextStyle: {//副标題文本樣式{"color": "#aaa"}
fontSize: fontChart(12),
color:'#fff'
},
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical', //horizontal vertical
left: 'left',
align:'left',
top:'middle',
itemWidth: fontChart(20), // 設定寬度
itemHeight: fontChart(10), // 設定高度
textStyle: {
color:'#fff',
fontSize:fontChart(12)
}
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
data: props.dataList,
center: ['65%','50%'],
label: {
normal: {
show: true,
position:'outside', //outside、inside同inner、center 可選
formatter: '{c}',
fontSize:fontChart(13)
},
},
emphasis: {
itemStyle: {
shadowBlur: fontChart(10),
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
charts.setOption(option)
window.addEventListener('resize', selfAdaption)
};
// 自适應
function selfAdaption() {
if(!charts) return
charts.resize()
drawPie()
}
</script>
4. 動态圓環(圖例自定義位置)
<template>
<div :id="id" style="width: 100%; height: 100%"></div>
</template>
<script>
import { fontChart } from "@/utils/echartPxToRem";
import * as echarts from "echarts";
export default {
data() {
return {
charts: "",
timer: null,
};
},
props: {
id: {
type: String,
required: true, //聲明這個參數是否必須傳入
},
dataList: {
type: Array,
default: () => ([
{
name: "平平果蔬種植基地",
value: 2,
},
{
name: "馥羽草莓基地",
value: 8,
},
{
name: "紅梅家庭農場",
value: 4,
},
{
name: "三郭城家庭農場",
value: 8,
},
{
name: "嘉祺農業基地",
value: 4,
},
])
}
},
watch: {
dataList() {
this.drawBar();
},
},
mounted() {
this.drawBar();
},
destroyed() {
window.removeEventListener("resize", this.selfAdaption);
if (this.timer) clearInterval(this.timer);
},
methods: {
drawBar() {
this.charts = echarts.init(document.getElementById(this.id));
let angle = 0;
let data = [];
let data2 = [];
var color = [
"#2A8BFD",
"#BAFF7F",
"#00FAC1",
"#00CAFF",
"#FDE056",
"#4ED33C",
"#FF8A26",
"#FF5252",
"#9689FF",
"#CB00FF",
];
let lefts = ['6%', '6%', '70%', '70%', '70%']
let tops = ['25%', '55%', '10%', '40%', '70%']
let legendData = [];
let total = 0
this.dataList.forEach(item => {
total += item.value
})
for (let i = 0; i < this.dataList.length; i++) {
let bfb = parseInt((this.dataList[i].value / total) * 100) + '%'
legendData.push({
show: true,
icon: "circle", //'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
left: lefts[i],
top: tops[i],
itemWidth: fontChart(10),
itemHeight: fontChart(10),
itemStyle: {
color: color[i],
},
formatter: `{aa| `+ this.dataList[i].name +` }` + `\n\n` + `{bb| ` +bfb+ `}`, // 也可以是個函數return
x: "left",
textStyle: {
// color: "#BAFF7F",
rich: {
aa: {
color: "#ffffff",
},
bb: {
color: color[i]
}
}
},
data: [this.dataList[i].name],
});
data.push(
{
value: this.dataList[i].value,
name: this.dataList[i].name,
itemStyle: {
normal: {
borderWidth: 8,
shadowBlur: 20,
borderRadius: 20,
borderColor: color[i],
shadowColor: color[i],
},
},
},
{
value: 1.5,
name: "",
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: "rgba(0, 0, 0, 0)",
borderColor: "rgba(0, 0, 0, 0)",
borderWidth: 0,
},
},
}
);
data2.push(
{
value: this.dataList[i].value,
name: this.dataList[i].name,
},
{
value: 5,
name: "",
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: "rgba(0, 0, 0, 0)",
borderColor: "rgba(0, 0, 0, 0)",
borderWidth: 0,
opacity: 0.2,
},
},
}
);
}
let option = {
// backgroundColor: "#061740",
// color: color,
legend: legendData,
series: [
{
//外線1
name: "",
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
return {
type: "arc",
shape: {
cx: api.getWidth() / 2,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
startAngle: ((0 + angle) * Math.PI) / 180,
endAngle: ((90 + angle) * Math.PI) / 180,
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5,
},
silent: true,
};
},
data: [0],
},
{
//内線1
name: "",
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
return {
type: "arc",
shape: {
cx: api.getWidth() / 2,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
startAngle: ((180 + angle) * Math.PI) / 180,
endAngle: ((270 + angle) * Math.PI) / 180,
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5,
},
silent: true,
};
},
data: [0],
},
{
//外線2
name: "",
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
return {
type: "arc",
shape: {
cx: api.getWidth() / 2,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
startAngle: ((270 + -angle) * Math.PI) / 180,
endAngle: ((40 + -angle) * Math.PI) / 180,
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5,
},
silent: true,
};
},
data: [0],
},
{
//外線2
name: "",
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
return {
type: "arc",
shape: {
cx: api.getWidth() / 2,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
startAngle: ((90 + -angle) * Math.PI) / 180,
endAngle: ((220 + -angle) * Math.PI) / 180,
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5,
},
silent: true,
};
},
data: [0],
},
{
//綠點1
name: "",
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
let x0 = api.getWidth() / 2;
let y0 = api.getHeight() / 2;
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65;
let point = this.getCirlPoint(x0, y0, r, 90 + -angle);
return {
type: "circle",
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: "#66FFFF", //粉
fill: "#66FFFF",
},
silent: true,
};
},
data: [0],
},
{
//綠點2
name: "", //綠點
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
let x0 = api.getWidth() / 2;
let y0 = api.getHeight() / 2;
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65;
let point = this.getCirlPoint(x0, y0, r, 270 + -angle);
return {
type: "circle",
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: "#66FFFF", //粉
fill: "#66FFFF",
},
silent: true,
};
},
data: [0],
},
{
//綠點3
name: "",
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
let x0 = api.getWidth() / 2;
let y0 = api.getHeight() / 2;
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6;
let point = this.getCirlPoint(x0, y0, r, 90 + angle);
return {
type: "circle",
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: "#66FFFF", //粉
fill: "#66FFFF",
},
silent: true,
};
},
data: [0],
},
{
//綠點4
name: "", //綠點
type: "custom",
coordinateSystem: "none",
renderItem: (params, api) => {
let x0 = api.getWidth() / 2;
let y0 = api.getHeight() / 2;
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6;
let point = this.getCirlPoint(x0, y0, r, 270 + angle);
return {
type: "circle",
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: "#66FFFF", //粉
fill: "#66FFFF",
},
silent: true,
};
},
data: [0],
},
{
name: "",
type: "pie",
clockWise: false,
radius: ["98%", "95%"],
hoverAnimation: false,
center: ["50%", "50%"],
top: "center",
itemStyle: {
normal: {
label: {
show: false,
},
},
},
data: data,
},
{
type: "pie",
top: "center",
startAngle: 90,
clockwise: false,
center: ["50%", "50%"],
legendHoverLink: false,
hoverAnimation: false,
radius: ["94%", "55%"],
itemStyle: {
opacity: 0.15,
},
label: {
show: false,
position: "center",
},
labelLine: {
show: false,
},
data: data2,
},
{
name: "",
type: "pie",
clockWise: false,
center: ["50%", "50%"],
radius: ["39%", "38%"],
hoverAnimation: false,
top: "center",
itemStyle: {
normal: {
label: {
show: false,
},
},
},
data: data,
},
],
};
this.charts.setOption(option, true);
if(this.timer) clearInterval(this.timer)
this.timer = setInterval(() => {
angle = angle + 3;
this.charts.setOption(option, true);
}, 100);
window.addEventListener("resize", this.selfAdaption);
},
//擷取圓上面某點的坐标(x0,y0表示坐标,r半徑,angle角度)
getCirlPoint(x0, y0, r, angle) {
let x1 = x0 + r * Math.cos((angle * Math.PI) / 180);
let y1 = y0 + r * Math.sin((angle * Math.PI) / 180);
return {
x: x1,
y: y1,
};
},
// 自适應
selfAdaption() {
if (!this.charts) return;
this.charts.resize();
clearInterval(this.timer);
this.drawBar();
},
},
};
</script>
5. 圓環嵌套
<template>
<div :id="id" style="width: 100%; height: 100%"></div>
</template>
<script setup>
import { fontChart } from "@/utils/echartPxToRem";
import * as echarts from "echarts";
import { onMounted, watch, onUnmounted, computed } from "vue";
const props = defineProps({
id: {
type: String,
required: true, //聲明這個參數是否必須傳入
},
dataList: {
type: Array,
default: () => [
{
name: "過高",
value: 60,
},
{
name: "偏高",
value: 40,
},
{
name: "正常",
value: 20,
},
],
},
});
watch(
() => props.dataList,
(newValue) => {
drawPie();
},
{
deep: true,
}
);
let charts = ""; // 這裡不要讓它成為響應式
const total = computed(() => {
let total = 0;
props.dataList.forEach((item) => {
total += item.value;
});
return total;
});
onMounted(() => {
drawPie();
});
onUnmounted(() => {
window.removeEventListener("resize", selfAdaption);
});
// 初始化echarts
const drawPie = () => {
charts = echarts.init(document.getElementById(props.id));
let arrName = getArrayValue(props.dataList, "name");
let arrValue = getArrayValue(props.dataList, "value");
let sumValue = getsumValue(props.dataList, "value");
let optionData = getData(props.dataList, sumValue);
let option = {
// backgroundColor: "RGB(8,20,67)",
grid: {
// top: "16%",
// bottom: "54%",
// left: "50%",
containLabel: false,
},
legend: {
show: false,
bottom: 6,
icon: "rect",
orient: "vertical",
itemHeight: 10,
itemWidth: 10,
left: 800,
top: 200,
show: true,
data: arrName,
selectedMode: false,
textStyle: {
color: "#96F5F6",
fontSize: 16,
},
formatter: (name) => {
let tarValue;
for (var i = 0; i < 4; i++) {
if (props.dataList[i].name == name) {
tarValue = props.dataList[i].value;
break;
}
}
var p = Math.round((tarValue / sumValue) * 1000) / 10;
return `${name} ${p}%`;
},
},
yAxis: [
{
type: "category",
inverse: true,
z: 3,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
interval: 0,
inside: false,
textStyle: {
color: "RGB(78,184,252)",
fontSize: 25,
},
},
data: optionData.yAxis,
},
],
xAxis: [
{
show: false,
},
],
series: optionData.series,
};
charts.setOption(option);
window.addEventListener("resize", selfAdaption);
};
function getsumValue(array, key) {
let sum = 0;
for (let i = 0; i < array.length; i++) {
sum = sum + array[i].value;
}
return sum;
}
function getArrayValue(array, key) {
var key = key || "value";
var res = [];
if (array) {
array.forEach(function (t) {
res.push(t[key]);
});
}
return res;
}
function getData(dataList, sumValue) {
let colorList2 = [
{
c1: "#fdd660",
c2: "#ffa934",
},
{
c1: "#03edff",
c2: "#1d7dff",
},
{
c1: "#4cfac1",
c2: "#15d481",
},
];
var res = {
series: [],
yAxis: [],
formatter: [],
};
for (let i = 1; i <= dataList.length; i++) {
res.series.push({
name: "學曆",
type: "pie",
clockWise: true,
z: 2,
hoverAnimation: false,
radius: [103 - i * 15 + "%", 95 - i * 15 + "%"],
center: ["50%", "50%"],
// label: {
// show: false,
// },
labelLine: {
show: false,
},
itemStyle: {
normal: {
label: {
show: true, //開啟顯示
position: "inside", //在上方顯示
textStyle: {
//數值樣式
color: "#fff",
fontSize: fontChart(10),
},
formatter: (data) => {
let value = data.value;
return ((value / total.value) * 100).toFixed(1) + "%";
},
textBorderColor: "#000",
textBorderWidth: 1,
},
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: colorList2[i - 1].c2,
},
{
offset: 1,
color: colorList2[i - 1].c1,
},
]),
},
},
data: [
{
value: dataList[i - 1].value,
name: dataList[i - 1].name,
},
{
value: sumValue - dataList[i - 1].value,
name: "",
itemStyle: {
color: "rgba(0,0,0,0)",
borderWidth: 0,
},
tooltip: {
show: false,
},
label: {
show: false,
},
hoverAnimation: false,
},
],
});
res.series.push({
name: "背景線",
type: "pie",
silent: true,
z: 1,
clockWise: true,
hoverAnimation: false,
radius: [100 - i * 15 + "%", 98 - i * 15 + "%"],
center: ["50%", "50%"],
label: {
show: false,
},
itemStyle: {
label: {
show: false,
},
labelLine: {
show: false,
},
borderWidth: 5,
},
data: [
{
value: 100,
itemStyle: {
color: "RGB(12,64,128)",
borderWidth: 0,
},
tooltip: {
show: false,
},
hoverAnimation: false,
},
],
});
res.yAxis.push(dataList[i - 1].name);
}
return res;
}
// 自适應
function selfAdaption() {
if (!charts) return;
charts.resize();
drawPie();
}
</script>
6. 儀表盤進度
<template>
<div :id="id" style="width: 100%; height: 100%"></div>
</template>
<script setup>
import { fontChart } from "@/utils/echartPxToRem";
import * as echarts from "echarts";
import { onMounted, watch, onUnmounted } from "vue";
const props = defineProps({
id: {
type: String,
required: true,
},
value: {
type: Number,
default: 65.23,
},
title: {
type: String,
default: "高尿酸",
},
});
watch(
() => props.value,
(newValue) => {
drawPie();
},
{
deep: true,
}
);
let charts = ""; // 這裡不要讓它成為響應式
let timer = null;
onMounted(() => {
drawPie();
});
onUnmounted(() => {
window.removeEventListener("resize", selfAdaption);
if (timer) clearInterval(timer);
});
// 初始化echarts
const drawPie = () => {
charts = echarts.init(document.getElementById(props.id));
let int = props.value.toFixed(2).split(".")[0];
let float = props.value.toFixed(2).split(".")[1];
let option = {
backgroundColor: "transparent",
title: {
text: "{a|" + int + "}{b|." + float + "}\n{c|" + props.title + "}",
x: "center",
y: "center",
textStyle: {
rich: {
a: {
fontSize: fontChart(15),
color: "#fff",
fontWeight: "600",
},
b: {
fontSize: fontChart(15),
color: "#fff",
padding: [0, 0, 0, 0],
},
c: {
fontSize: fontChart(15),
color: "#fff",
padding: [5, 0],
},
},
},
},
series: [
{
type: "gauge",
radius: "60%",
clockwise: false,
startAngle: "90",
endAngle: "-269.9999",
splitNumber: 30,
detail: {
offsetCenter: [0, -20],
formatter: " ",
},
pointer: {
show: false,
},
axisLine: {
show: true,
lineStyle: {
color: [
[0, "#2CFAFC"],
[36.7 / 100, "#0ff"],
[1, "#0f232e"],
],
width: 20,
},
},
axisTick: {
show: false,
},
splitLine: {
show: true,
length: 120,
lineStyle: {
shadowBlur: 10,
shadowColor: "rgba(0, 255, 255, 1)",
shadowOffsetY: "0",
color: "#020f18",
width: 2,
},
},
axisLabel: {
show: false,
},
},
{
type: "pie",
radius: ["64%", "65%"],
hoverAnimation: false,
clockWise: false,
itemStyle: {
normal: {
color: "transparent",
},
},
label: {
show: false,
},
data: dashed(),
},
{
type: "pie",
radius: [0, "50%"],
hoverAnimation: false,
clockWise: false,
itemStyle: {
normal: {
shadowBlur: 20,
shadowColor: "#000",
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [
{
offset: 0,
color: "#0FF",
},
{
offset: 1,
color: "#060f20",
},
]),
},
},
label: {
show: false,
},
data: [100],
},
{
type: "pie",
radius: ["84%", "85.5%"],
hoverAnimation: false,
clockWise: false,
itemStyle: {
normal: {
shadowBlur: 20,
shadowColor: "rgba(0, 255, 255,.3)",
color: "#0f232e",
},
},
label: {
show: false,
},
data: [100],
},
{
type: "pie",
radius: ["88%", "89.5%"],
hoverAnimation: false,
clockWise: false,
itemStyle: {
normal: {
shadowBlur: 20,
shadowColor: "rgba(0, 255, 255,.3)",
color: "rgba(15, 35, 46,.6)",
},
},
label: {
show: false,
},
data: [100],
},
],
};
charts.setOption(option);
startTimer()
window.addEventListener("resize", selfAdaption);
};
function dashed() {
let dataArr = [];
for (var i = 0; i < 100; i++) {
if (i % 2 === 0) {
dataArr.push({
name: (i + 1).toString(),
value: 20,
itemStyle: {
normal: {
color: "rgb(0,255,255,.3)",
},
},
});
} else {
dataArr.push({
name: (i + 1).toString(),
value: 20,
itemStyle: {
normal: {
color: "rgb(0,0,0,0)",
borderWidth: 1,
borderColor: "rgba(0,255,255,1)",
},
},
});
}
}
return dataArr;
}
function doing() {
let option = charts.getOption();
option.series[1].startAngle = option.series[1].startAngle - 1;
charts.setOption(option);
}
function startTimer() {
if(timer) clearInterval(timer)
timer = setInterval(doing, 100);
}
// 自适應
function selfAdaption() {
if (!charts) return;
charts.resize();
drawPie();
}
</script>
7. 雙圓 (外層展示資料)
<!-- 雙圓 -->
<template>
<div style="width: 100%; height: 100%">
<div :id="id" style="width: 100%; height: 100%"></div>
</div>
</template>
<script>
import * as echarts from "echarts";
import { fontChart } from "@/utils/echartPxToRem.js";
export default {
data() {
return {
charts: "",
};
},
props: {
id: {
type: String,
required: true, //聲明這個參數是否必須傳入
},
value: {
type: Number,
default: 14251,
},
},
watch: {
data() {
this.drawPie();
},
},
mounted() {
this.drawPie();
},
destroyed() {
window.removeEventListener("resize", this.selfAdaption);
},
methods: {
drawPie() {
this.charts = echarts.init(document.getElementById(this.id));
// 指定圖表的配置項和資料
var option = {
title: {
// 總數樣式
text: "節能減排",
subtext: this.value,
x: "center",
y: "41%",
// 節能減排字型
textStyle: {
fontWeight: "600",
fontSize: 18,
color: "red",
},
// 數量樣式
subtextStyle: {
fontSize: 20,
color: "orange",
},
},
// 滑鼠移動到圖上時的提示消息
tooltip: {
show: false,
trigger: "item",
// formatter可以為函數,自定義提示資訊
// formatter: "{b}:{c}個<br/>占比:({d}%)"
formatter: function (item) {
return (
`<p> ` +
item.name +
` : 共 ` +
item.value +
` 個 </p> <br> <p> 占比 ` +
item.rate +
` % </p>`
);
},
},
series: [
{
itemStyle: {
normal: {},
},
type: "pie",
stillShowZeroSum: true,
radius: ["60%", "70%"],
label: {
normal: {
position: "inner",
show: false,
textStyle: {
color: "#fff",
fontSize: 12,
},
},
},
labelLine: {
normal: {
show: false,
},
},
data: [
{
name: "節能診斷",
value: this.value,
itemStyle: {
normal: { color: "#13d2ee" },
},
},
],
},
// 内層圓線
{
type: "pie",
hoverAnimation: false, //滑鼠經過的特效
radius: ["55%", "52%"],
center: ["50%", "50%"],
startAngle: 225,
labelLine: {
normal: {
show: false,
},
},
label: {
normal: {
position: "center",
},
},
data: [
{
value: 1,
itemStyle: {
normal: {
color: "rgba(32, 143, 173, 1)",
},
},
},
],
},
],
};
// 使用剛指定的配置項和資料顯示圖表。
this.charts.setOption(option);
window.addEventListener("resize", this.selfAdaption);
},
// 自适應
selfAdaption() {
if (!this.charts) return;
this.charts.resize();
this.drawPie();
},
},
};
</script>