123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- <!-- 五维雷达图 -->
- <template>
- <div :id="id" :class="className" :style="{ height, width }" />
- </template>
- <script setup lang="ts">
- import * as echarts from "echarts";
- const props = defineProps({
- id: {
- type: String,
- default: "radarChart",
- required: true,
- },
- className: {
- type: String,
- default: "chart",
- },
- width: {
- type: String,
- default: "400px",
- },
- height: {
- type: String,
- default: "300px",
- },
- color: {
- type: String,
- default: "#063b79",
- },
- // dataSets:[[训练后],[训练前]]
- // dataSets:[[78,88,65,82,65],[28,38,45,32,25]]
- dataSets: {
- type: Array,
- default: [] as Array<number>,
- },
- // star:[1,2,3,4,5]
- star: {
- type: Array,
- default: [] as Array<number>,
- },
- tag: {
- type: Boolean,
- default: false,
- },
- });
- // 是否有对比数据
- const isCompare = props.dataSets?.length > 1;
- const globalColor = {
- default: "#ffb72d",
- before: "#937dff",
- font: props.color,
- white: "#ffffff",
- red: "#F45028",
- orange: "#FF9F29",
- yellow: "#EDCB00",
- green: "#53BE07",
- blue: "#03C5EC",
- };
- /**
- * 指示器 及 状态tag 自定义rich
- */
- const tagBaseRich = (bgColor: string) => {
- return {
- color: globalColor.white,
- padding: [4, 10, 4, 10],
- borderRadius: 10,
- backgroundColor: bgColor,
- };
- };
- const indicatorRich = {
- tit: {
- color: globalColor.font,
- fontSize: 14,
- padding: 5,
- },
- red: tagBaseRich(globalColor.red),
- orange: tagBaseRich(globalColor.orange),
- yellow: tagBaseRich(globalColor.yellow),
- green: tagBaseRich(globalColor.green),
- blue: tagBaseRich(globalColor.blue),
- };
- const indicatorFormatter = (name: string, indicator: any) => {
- if (!props.tag) {
- return `{tit|${name}}`;
- }
- const { star } = indicator;
- const label = [];
- label.push(`{tit|${name}}`);
- if (star === 1) {
- label.push(`{red|重度不足}`);
- }
- if (star === 2) {
- label.push("{orange|轻度不足}");
- }
- if (star === 3) {
- label.push("{yellow|中等水平}");
- }
- if (star === 4) {
- label.push("{green|良好水平}");
- }
- if (star === 5) {
- label.push("{blue|优秀水平}");
- }
- return label.join(`\n`);
- };
- /**
- * 在图中定位每个数据的位置
- */
- const positionLabelData = (data: number[], idx: number) => {
- const labelValue: any = [0, 0, 0, 0, 0];
- labelValue[idx] = data[idx];
- // idx = 0,1,2,3,4 对应 top,left,bottom,bottom,right
- let pos = "bottom";
- if (idx === 0) {
- pos = "top";
- }
- if (idx === 1) {
- pos = "left";
- }
- if (idx === 4) {
- pos = "right";
- }
- return {
- value: labelValue,
- label: {
- show: true,
- fontSize: 12,
- position: pos,
- formatter: (params: any) => {
- return params.value > 0 ? params.value : "";
- },
- },
- };
- };
- const positionFormatter = (data: any) => {
- const result: any = [];
- for (let idx in data) {
- result.push(positionLabelData(data, Number(idx)));
- }
- return result;
- };
- /**
- * 配置项
- */
- const options = {
- color: [globalColor.default],
- legend: {
- right: "5%",
- top: "5%",
- data: [
- { name: "训练前", icon: "circle" },
- { name: "训练后", icon: "circle" },
- ],
- textStyle: { fontSize: 12 },
- show: false,
- },
- radar: {
- radius: "50%",
- center: ["50%", "55%"],
- // 指示器 及 状态tag
- indicator: [
- { name: "专注力平均值", max: 100, star: props.star?.[0] },
- { name: "高专注占比", max: 100, star: props.star?.[1] },
- { name: "专注唤醒效率", max: 100, star: props.star?.[2] },
- { name: "整体和谐度", max: 100, star: props.star?.[3] },
- { name: "专注力稳定度", max: 100, star: props.star?.[4] },
- ],
- axisName: {
- rich: indicatorRich,
- formatter: indicatorFormatter,
- },
- },
- series: [
- // 数据分散定位
- {
- name: "训练后",
- type: "radar",
- symbolSize: 0,
- label: {
- show: true,
- color: globalColor.default,
- fontSize: 16,
- distance: 5,
- },
- lineStyle: { width: 0 },
- data: positionFormatter(props.dataSets?.[0]),
- },
- // 覆盖区域的样式
- {
- name: "训练前 vs 训练后",
- type: "radar",
- symbolSize: 5,
- data: [
- {
- value: props.dataSets?.[0],
- name: "训练后",
- lineStyle: { color: globalColor.default },
- itemStyle: { color: globalColor.default },
- areaStyle: {
- color: globalColor.default,
- opacity: 0.5,
- },
- },
- ],
- },
- ],
- };
- const getOptions = () => {
- if (isCompare) {
- options.color = [globalColor.before, globalColor.default];
- options.legend.show = true;
- options.series[1].data.unshift({
- value: props.dataSets?.[1],
- name: "训练前",
- lineStyle: { color: globalColor.before },
- itemStyle: { color: globalColor.before },
- areaStyle: {
- color: globalColor.before,
- opacity: 0.5,
- },
- });
- options.series.unshift({
- name: "训练前",
- type: "radar",
- symbolSize: 0,
- label: {
- show: true,
- color: globalColor.before,
- fontSize: 16,
- distance: 0,
- },
- lineStyle: { width: 0 },
- data: positionFormatter(props.dataSets?.[1]),
- });
- }
- return options;
- };
- onMounted(() => {
- const chart = echarts.init(
- document.getElementById(<string>props.id) as HTMLDivElement
- );
- chart.setOption(getOptions());
- window.addEventListener("resize", () => {
- chart.resize();
- });
- });
- </script>
|