在vue3中,如何优雅的使用echarts之实现大屏项目

前置知识 

效果图

使用技术 

Vue3 + Echarts + Gasp

Gasp:是一个 JavaScript动画库,它支持快速开发高性能的 Web 动画。在本项目中,主要是用于做轨迹运动

所需安装的插件
npm i echarts
npm i countup.js 数字滚动特效
npm i gsap javascript动画库
npm i axios
npm i normalize.css 初始化样式文件 
npm i lodash javascript工具函数库    https://www.lodashjs.com/
npm i sass css预处理工具 

适配目标

1920*1080px 设计稿尺寸

目标设备:16:9

前期准备

封装echarts

在大屏中,如果每个图表都去单独写 init 以及进行resize监听机会显得很麻烦,这里我们可以将这些重复的步骤封装成一个hooks,这样在使用的时候就可以统一的进行初始化和进行resize监听。

具体代码如下:

src/hooks/useEcharts.js

import * as echarts from "echarts";
import { ref, onMounted, onUnmounted } from "vue";export default function useEchart(divEl) {// 参数一:DOM容器,参数二:主题色,参数三:渲染方式let echartInstance = echarts.init(divEl, null, { renderer: "svg" });onUnmounted(() => {// 销毁实例echartInstance.dispose()})const setOption = (option) => {echartInstance.setOption(option)}const resizeEchart = () => {echartInstance.resize()}return {echartInstance,setOption,resizeEchart}
}

 

封装sclae

这里我们可以新建一个 useScalePage hooks,目的在于随着浏览器视口的变化是,大屏能够随之跟着变化,但是为了限制用户在一定时间内去频繁的改变浏览器视口,因此这里我们可以利用lodash的throttle节流阀进行限制

主要思路:

  • 根据当前设计稿的宽高以及宽高比,再获取当前设备的即浏览器的宽高。
  • 通过当前设备的宽度比上当前设计稿的宽度,从而获取到默认情况下的一个宽高比例
  • 再通过当前设备的宽度比上当前设备的高度,从而获取到当前情况下的一个宽高比例

代码入下:

useScalePage.js

import { onMounted, onUnmounted } from 'vue';
import _ from 'lodash' /**大屏适配的 hooks*/
export default function useScalePage(option) {const resizeFunc = _.throttle(function() {triggerScale() // 动画缩放网页}, 100)onMounted(()=>{triggerScale()  // 动画缩放网页window.addEventListener('resize', resizeFunc)})// 释放资源onUnmounted(()=>{window.removeEventListener('resize', resizeFunc) // 释放})// 大屏的适配function triggerScale() {// 1.设计稿的尺寸let targetX = option.targetX ||  1920let targetY = option.targetY || 1080let targetRatio = option.targetRatio ||  16 / 9 // 宽高比率// 2.拿到当前设备(浏览器)的宽度let currentX = document.documentElement.clientWidth || document.body.clientWidthlet currentY = document.documentElement.clientHeight || document.body.clientHeight// 3.计算缩放比例let scaleRatio = currentX / targetX; // 参照宽度进行缩放 ( 默认情况 )let currentRatio = currentX / currentY // 宽高比率// 超宽屏if(currentRatio > targetRatio) {// 4.开始缩放网页scaleRatio = currentY / targetY // 参照高度进行缩放document.body.style = `width:${targetX}px; height:${targetY}px;transform: scale(${scaleRatio}) translateX(-50%); left: 50%`} else {// 4.开始缩放网页document.body.style = `width:${targetX}px; height:${targetY}px; transform: scale(${scaleRatio})`}}
}

 

请求方法封装

services/request/config.js  该文件的目的就是存放一些常量配置,比如:请求地址、超时时间等

export const BASE_URL = "http://123.207.32.32:9060/beike/api"
export const TIMEOUT = 10000

services/index.js

import axios from 'axios'
import { BASE_URL, TIMEOUT } from './config'
class LWJRequest {constructor(baseURL = BASE_URL, timeout= TIMEOUT) {this.instance = axios.create({baseURL,timeout})}request(config) {return new Promise((resolve, reject) => {this.instance.request(config).then(res => {resolve(res.data)}).catch(err => {reject(err)})})}get(config) {return this.request({ ...config, method: "get" })}post(config) {return this.request({ ...config, method: "post" })}
}
export default new LWJRequest()

 

图表封装 

这里封装的组件放置在 components 里,具体代码如下所示:

饼图封装

pie-echarts.vue

<template><div :style="{ width: width, height: height }" ref="divRef"></div>
</template><script setup>
import { ref, onMounted, watch } from "vue";
import useEchart from "@/hooks/useEchart";const props = defineProps({width: {type: String,default: "100%",},height: {type: String,default: "100%",},echartsChargingPileData: {type: Array,default: function () {return [];},},
});// 监听 echartDatas 的变化
watch(() => props.echartsChargingPileData, (newV, oldV) => {setupEchart(newV);}
);// 获取dom元素
let divRef = ref(null);
let myChart = null;onMounted(() => {setupEchart(props.echartsChargingPileData); // 第一次走这里
});function setupEchart(echartDatas = []) {if (!myChart) {myChart = useEchart(divRef.value);}let option = getOption(echartDatas); // 准备数据myChart.setOption(option);
}function getOption(pieDatas = []) {let colors = pieDatas.map((item) => {return item.color;});let data = pieDatas.map((item) => {return {value: item.value,name: item.name,};});let total = pieDatas.reduce((a, b) => {return a + b.value * 1;}, 0);const option = {colors: colors,title: {text: `{nameSty| 充电桩总数}\n{numberSty|${total}}`,top: "50%",left: "30%",textStyle: {rich: {nameSty: {fontSize: 19,color: "white",padding: [10, 0],},numberSty: {fontSize: 24,color: "white",padding: [4, 0, 0, 20],},},},},legend: {orient: "vertical",right: "10%",top: "18%",itemGap: 20,itemWidth: 16,itemHeigth: 16,icon: "rect",// 格式化图例文本formatter: function (name) {var currentItem = pieDatas.find((item) => item.name === name);return ("{nameSty|" +currentItem.name +"}\n" +"{numberSty|" +currentItem.value +"个 }" +"{preSty|" +currentItem.percentage +"}");},textStyle: {rich: {nameSty: {fontSize: 12,color: "#FFFFFF",padding: [10, 14],},numberSty: {fontSize: 12,color: "#40E6ff",padding: [0, 0, 0, 14],},preSty: {fontSize: 12,color: "#40E6ff",},},},},series: [{type: "pie",center: ["40%", "57%"],radius: ["30%", "75%"],label: {show: false,},data: data,roseType: "area",},],};return option;
}
</script><style lang="scss" scoped></style>
折线图

line-echarts.js

<template><div ref="divRef" :style="{ width: width, height: height }"></div>
</template><script setup>
import { ref, onMounted, watch } from "vue";
import useEchart from "@/hooks/useEchart";const props = defineProps({width: {type: String,default: "100%",},height: {type: String,default: "100%",},echartsPrecessMonitoringData: {type: Array,default: function () {return [];},},
});// 监听 echartDatas 的变化
watch(() => props.echartsPrecessMonitoringData, (newV, oldV) => {setupEchart(newV);}
);// 获取dom元素
let divRef = ref(null);
let myChart = null;onMounted(() => {setupEchart(props.echartsPrecessMonitoringData); // 第一次走这里
});function setupEchart(echartDatas = []) {if (!myChart) {myChart = useEchart(divRef.value);}let option = getOption(echartDatas); // 准备数据myChart.setOption(option);
}function getOption(echartDatas = []) {let option = {// backgroundColor: 'rbg(40,46,72)',grid: {left: "5%",right: "1%",top: "20%",bottom: "15%",containLabel: true, // grid 区域是否包含坐标轴的刻度标签},legend: {right: "center",bottom: "5%",itemGap: 20,itemWidth: 13,itemHeigth: 12,textStyle: {color: "#64BCFF",},icon: "rect",},tooltip: {trigger: "axis",axisPointer: {type: "line",lineStyle: {color: "#20FF89",},},},xAxis: [{type: "category",axisLine: {show: false,},axisLabel: {color: "#64BCFF",},splitLine: {show: false,},axisTick: {show: false,},data: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月",],},],yAxis: [{type: "value",splitLine: {show: false,},axisLine: {show: false,},axisLabel: {show: true,color: "#64BCFF",},},],series: [{name: echartDatas[0].name,type: "line",smooth: true,stack: "总量",symbolSize: 5,showSymbol: false,itemStyle: {color: "#20FF89",lineStyle: {color: "#20FF89",width: 2,},},areaStyle: {color: {type: "linear",x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: "#20FF89",},{offset: 1,color: "rgba(255, 255, 255, 0)",},],},},data: echartDatas[0].data,},{name: echartDatas[1].name,type: "line",smooth: true,stack: "总量",symbolSize: 5,showSymbol: false,itemStyle: {color: "#EA9502",lineStyle: {color: "#EA9502",width: 2,},},areaStyle: {color: {type: "linear",x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: "#EA9502",},{offset: 1,color: "rgba(255, 255, 255, 0)",},],},},data:  echartDatas[1].data,},],};return option
}
</script><style lang="scss" scoped></style>

柱状图

bar-echarts.vue

<template><div ref="divRef" :style="{ width: width, height: height }"></div>
</template><script setup>
import { ref, onMounted, watch } from "vue";
import useEchart from "@/hooks/useEchart";const props = defineProps({width: {type: String,default: "100%",},height: {type: String,default: "100%",},echartsChargingStatisticsData: {type: Array,default: function () {return [];},},
});// 监听 echartDatas 的变化
watch(() => props.echartsChargingStatisticsData,(newV, oldV) => {setupEchart(newV);}
);// 获取dom元素
let divRef = ref(null);
let myChart = null;onMounted(() => {setupEchart(props.echartsChargingStatisticsData); // 第一次走这里
});function setupEchart(echartDatas = []) {if (!myChart) {myChart = useEchart(divRef.value);}let option = getOption(echartDatas); // 准备数据myChart.setOption(option);
}function getOption(echartDatas = []) {let category = echartDatas.map(item => item.name)let categoryData = echartDatas.map(item => item.value)const option = {// backgroundColor: 'rbg(40,46,72)',grid: {left: "5%",right: "5%",top: "30%",bottom: "5%",containLabel: true, // grid 区域是否包含坐标轴的刻度标签},tooltip: {},xAxis: {axisLine: {show: true,lineStyle: {color: "#42A4FF",},},axisTick: {show: false,},axisLabel: {color: "white",},// data: ["一月", "二月", "三月", "四月", "五月", "六月", "七月"],data: category},yAxis: {name: "个",nameTextStyle: {color: "white",fontSize: 13,},axisLine: {show: true,lineStyle: {color: "#42A4FF",},},axisTick: {show: false,},splitLine: {show: true,lineStyle: {color: "#42A4FF",},},axisLabel: {color: "white",},},series: [{name: "销量",type: "bar",barWidth: 17,itemStyle: {color: {type: "linear",x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: "#01B1FF", // 0% 处的颜色},{offset: 1,color: "#033BFF", // 100% 处的颜色},],global: false, // 缺省为 false},},// data: [500, 2000, 3600, 1000, 1000, 2000, 4000],data: categoryData},],};return option;
}
</script><style lang="scss" scoped></style>

其他区域封装

center-svg.vue
<template><div class="center-svg"><svgid="dongxiao"data-name="dongxiao"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"width="787.781"height="652"viewBox="0 0 787.781 652"><defs><linearGradientid="linear-gradient"x1="177.891"y1="126.344"x2="177.891"y2="51.375"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#030000" /><stop offset="1" stop-color="#fff" /></linearGradient><linearGradientid="linear-gradient-2"x1="177.891"y1="110.344"x2="177.891"y2="44.719"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-3"x1="177.969"y1="90.719"x2="177.969"y2="-0.625"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#26bbff" /><stop offset="1" stop-color="#26bbff" stop-opacity="0" /></linearGradient><linearGradientid="linear-gradient-4"x1="177.969"y1="91.219"x2="177.969"y2="46.875"gradientUnits="userSpaceOnUse"><stop offset="-0.055" stop-color="#26bbff" /><stop offset="1.044" stop-color="#26bbff" stop-opacity="0" /><stop offset="1.055" stop-color="#26bbff" /></linearGradient><linearGradientid="linear-gradient-5"x1="178.109"y1="87.563"x2="178.109"y2="38"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" /><stop offset="1" stop-color="#fff" stop-opacity="0" /></linearGradient><linearGradientid="linear-gradient-6"x1="718.89"y1="414.344"x2="718.89"y2="339.375"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-7"x1="718.89"y1="398.344"x2="718.89"y2="332.719"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-8"x1="718.969"y1="378.719"x2="718.969"y2="287.375"xlink:href="#linear-gradient-3"/><linearGradientid="linear-gradient-9"x1="718.968"y1="379.219"x2="718.968"y2="334.875"xlink:href="#linear-gradient-4"/><linearGradientid="linear-gradient-10"x1="719.109"y1="375.562"x2="719.109"y2="326"xlink:href="#linear-gradient-5"/><linearGradientid="linear-gradient-11"x1="67.891"y1="325.344"x2="67.891"y2="250.375"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-12"x1="67.891"y1="309.344"x2="67.891"y2="243.719"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-13"x1="67.969"y1="289.719"x2="67.969"y2="198.375"xlink:href="#linear-gradient-3"/><linearGradientid="linear-gradient-14"x1="67.969"y1="290.219"x2="67.969"y2="245.875"xlink:href="#linear-gradient-4"/><linearGradientid="linear-gradient-15"x1="68.109"y1="286.562"x2="68.109"y2="237"xlink:href="#linear-gradient-5"/><linearGradientid="linear-gradient-16"x1="159.891"y1="596.344"x2="159.891"y2="521.375"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-17"x1="159.891"y1="580.344"x2="159.891"y2="514.719"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-18"x1="159.969"y1="560.719"x2="159.969"y2="469.375"xlink:href="#linear-gradient-3"/><linearGradientid="linear-gradient-19"x1="159.969"y1="561.219"x2="159.969"y2="516.875"xlink:href="#linear-gradient-4"/><linearGradientid="linear-gradient-20"x1="160.109"y1="557.562"x2="160.109"y2="508"xlink:href="#linear-gradient-5"/><linearGradientid="linear-gradient-21"x1="581.89"y1="623.344"x2="581.89"y2="548.375"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-22"x1="581.89"y1="607.344"x2="581.89"y2="541.719"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-23"x1="581.969"y1="587.719"x2="581.969"y2="496.375"xlink:href="#linear-gradient-3"/><linearGradientid="linear-gradient-24"x1="581.968"y1="588.219"x2="581.968"y2="543.875"xlink:href="#linear-gradient-4"/><linearGradientid="linear-gradient-25"x1="582.109"y1="584.562"x2="582.109"y2="535"xlink:href="#linear-gradient-5"/><linearGradientid="linear-gradient-26"x1="633.89"y1="145.344"x2="633.89"y2="70.375"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-27"x1="633.89"y1="129.344"x2="633.89"y2="63.719"xlink:href="#linear-gradient"/><linearGradientid="linear-gradient-28"x1="633.969"y1="109.719"x2="633.969"y2="18.375"xlink:href="#linear-gradient-3"/><linearGradientid="linear-gradient-29"x1="633.968"y1="110.219"x2="633.968"y2="65.875"xlink:href="#linear-gradient-4"/><linearGradientid="linear-gradient-30"x1="634.109"y1="106.562"x2="634.109"y2="57"xlink:href="#linear-gradient-5"/><linearGradientid="linear-gradient-31"x1="273.219"y1="315.25"x2="524.25"y2="443.156"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fbab00" /><stop offset="0.342" stop-color="#f98100" /><stop offset="0.75" stop-color="#f86d00" stop-opacity="0" /><stop offset="1" stop-color="#f86000" /></linearGradient><linearGradientid="linear-gradient-32"x1="565.875"y1="379.485"x2="235.062"y2="379.485"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1b90ff" /><stop offset="0.745" stop-color="#0752ff" stop-opacity="0" /><stop offset="1" stop-color="#003dff" /></linearGradient><linearGradientid="linear-gradient-33"x1="628.344"y1="445.411"x2="169.406"y2="278.371"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fbab00" /><stop offset="0.342" stop-color="#f98100" /><stop offset="1" stop-color="#f86000" stop-opacity="0" /></linearGradient><filterid="filter"x="291"y="214"width="61"height="60"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-2"x="258"y="155"width="61"height="61"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><!-- 蓝色点滤镜效果 --><filter id="blue-filter-2" filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><!-- 橙色点滤镜特效 --><filter id="orange-filter-2" filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#f97a00" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-3"x="126"y="296"width="61"height="61"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-4"x="255"y="269"width="61"height="61"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-5"x="226"y="510"width="60"height="61"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-6"x="256"y="452"width="60"height="60"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-7"x="257"y="407"width="61"height="61"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-8"x="247"y="83"width="59"height="59"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-9"x="262"y="122"width="60"height="59"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-10"x="278"y="199"width="59"height="60"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-11"x="112"y="294"width="59"height="59"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-12"x="206"y="274"width="59"height="59"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-13"x="255"y="436"width="59"height="60"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-14"x="238"y="500"width="59"height="59"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="filter-15"x="279"y="364"width="59"height="59"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#1783ff" flood-opacity="0.9" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><imageid="image"width="23"height="23"xlink:href="../assets/images/center/image-1.png"/><imageid="image-2"width="15"height="15"xlink:href="../assets/images/center/image-2.png"/></defs><g id="dongxiao1"><g id="icon"><pathid="base_o"class="cls-1"d="M177.9,51.386c33.127,0,63.736,13.839,67.114,34,3.557,21.237-26.042,40.948-67.114,40.948s-70.671-19.711-67.113-40.948C114.162,65.225,144.771,51.386,177.9,51.386Z"/><pathid="base_t"class="cls-2"d="M177.9,44.728c33.127,0,63.736,12.114,67.114,29.76,3.557,18.59-26.042,35.844-67.114,35.844s-70.671-17.254-67.113-35.844C114.162,56.842,144.771,44.728,177.9,44.728Z"/><pathid="right_o"class="cls-3"d="M122.484-.626H233.455L208.447,90.7H147.491Z"/><pathid="right_t"class="cls-4"d="M112.064,46.866H243.875l-35.428,44.36H147.491Z"/><pathid="line"class="cls-5"d="M178.105,38c25.911,0,51.58,8.076,56.087,21.076,4.881,14.075-19.143,28.5-56.083,28.5s-60.966-14.426-56.087-28.5C126.527,46.072,152.194,38,178.105,38Z"/><imageid="icon_star_guangzhou"x="121"y="-3"width="112"height="112"xlink:href="../assets/images/center/star.png"/><pathid="base_o-2"data-name="base_o"class="cls-6"d="M718.9,339.386c33.127,0,63.736,13.839,67.114,34,3.557,21.237-26.042,40.948-67.114,40.948s-70.671-19.711-67.113-40.948C655.162,353.225,685.771,339.386,718.9,339.386Z"/><pathid="base_t-2"data-name="base_t"class="cls-7"d="M718.9,332.728c33.127,0,63.736,12.114,67.114,29.76,3.557,18.59-26.042,35.844-67.114,35.844s-70.671-17.254-67.113-35.844C655.162,344.842,685.771,332.728,718.9,332.728Z"/><pathid="right_o-2"data-name="right_o"class="cls-8"d="M663.484,287.374H774.455L749.447,378.7H688.491Z"/><pathid="right_t-2"data-name="right_t"class="cls-9"d="M653.064,334.866H784.875l-35.428,44.36H688.491Z"/><pathid="line-2"data-name="line"class="cls-10"d="M719.105,326c25.911,0,51.58,8.076,56.087,21.076,4.881,14.075-19.143,28.5-56.083,28.5s-60.966-14.426-56.087-28.5C667.527,334.072,693.194,326,719.105,326Z"/><imageid="icon_location_zhongshan"x="666"y="287"width="106"height="107"xlink:href="../assets/images/center/location.png"/><pathid="base_o-3"data-name="base_o"class="cls-11"d="M67.9,250.386c33.127,0,63.736,13.839,67.114,34,3.557,21.237-26.042,40.948-67.114,40.948S-2.773,305.62.785,284.383C4.162,264.225,34.771,250.386,67.9,250.386Z"/><pathid="base_t-3"data-name="base_t"class="cls-12"d="M67.9,243.728c33.127,0,63.736,12.114,67.114,29.76,3.557,18.59-26.042,35.844-67.114,35.844S-2.773,292.078.785,273.488C4.162,255.842,34.771,243.728,67.9,243.728Z"/><pathid="right_o-3"data-name="right_o"class="cls-13"d="M12.484,198.374H123.455L98.447,289.7H37.491Z"/><pathid="right_t-3"data-name="right_t"class="cls-14"d="M2.064,245.866H133.875l-35.428,44.36H37.491Z"/><pathid="line-3"data-name="line"class="cls-15"d="M68.105,237c25.911,0,51.58,8.076,56.087,21.076,4.881,14.075-19.143,28.5-56.083,28.5s-60.966-14.426-56.088-28.5C16.527,245.072,42.194,237,68.105,237Z"/><imageid="icon_pie_shenzhen"x="13"y="194"width="107"height="108"xlink:href="../assets/images/center/pie.png"/><pathid="base_o-4"data-name="base_o"class="cls-16"d="M159.9,521.386c33.127,0,63.736,13.839,67.114,34,3.557,21.237-26.042,40.948-67.114,40.948S89.227,576.62,92.785,555.383C96.162,535.225,126.771,521.386,159.9,521.386Z"/><pathid="base_t-4"data-name="base_t"class="cls-17"d="M159.9,514.728c33.127,0,63.736,12.114,67.114,29.76,3.557,18.59-26.042,35.844-67.114,35.844s-70.671-17.254-67.113-35.844C96.162,526.842,126.771,514.728,159.9,514.728Z"/><pathid="right_o-4"data-name="right_o"class="cls-18"d="M104.484,469.374H215.455L190.447,560.7H129.491Z"/><pathid="right_t-4"data-name="right_t"class="cls-19"d="M94.064,516.866H225.875l-35.428,44.36H129.491Z"/><pathid="line-4"data-name="line"class="cls-20"d="M160.1,508c25.911,0,51.58,8.076,56.087,21.076,4.881,14.075-19.143,28.5-56.083,28.5s-60.966-14.426-56.088-28.5C108.527,516.072,134.194,508,160.1,508Z"/><imageid="icon_earth_dongguan"x="106"y="460"width="111"height="112"xlink:href="../assets/images/center/earth.png"/><pathid="base_o-5"data-name="base_o"class="cls-21"d="M581.9,548.386c33.127,0,63.736,13.839,67.114,34,3.557,21.237-26.042,40.948-67.114,40.948s-70.671-19.711-67.113-40.948C518.162,562.225,548.771,548.386,581.9,548.386Z"/><pathid="base_t-5"data-name="base_t"class="cls-22"d="M581.9,541.728c33.127,0,63.736,12.114,67.114,29.76,3.557,18.59-26.042,35.844-67.114,35.844s-70.671-17.254-67.113-35.844C518.162,553.842,548.771,541.728,581.9,541.728Z"/><pathid="right_o-5"data-name="right_o"class="cls-23"d="M526.484,496.374H637.455L612.447,587.7H551.491Z"/><pathid="right_t-5"data-name="right_t"class="cls-24"d="M516.064,543.866H647.875l-35.428,44.36H551.491Z"/><pathid="line-5"data-name="line"class="cls-25"d="M582.105,535c25.911,0,51.58,8.076,56.087,21.076,4.881,14.075-19.143,28.5-56.083,28.5s-60.966-14.426-56.087-28.5C530.527,543.072,556.194,535,582.105,535Z"/><imageid="icon_hot_zhuhai"x="530"y="495"width="105"height="105"xlink:href="../assets/images/center/hot.png"/><pathid="base_o-6"data-name="base_o"class="cls-26"d="M633.9,70.386c33.127,0,63.737,13.839,67.114,34,3.557,21.237-26.042,40.948-67.114,40.948s-70.671-19.711-67.113-40.948C570.162,84.225,600.771,70.386,633.9,70.386Z"/><pathid="base_t-6"data-name="base_t"class="cls-27"d="M633.9,63.728c33.127,0,63.737,12.114,67.114,29.76,3.557,18.59-26.042,35.844-67.114,35.844s-70.671-17.254-67.113-35.844C570.162,75.842,600.771,63.728,633.9,63.728Z"/><pathid="right_o-6"data-name="right_o"class="cls-28"d="M578.484,18.374H689.455L664.447,109.7H603.491Z"/><pathid="right_t-6"data-name="right_t"class="cls-29"d="M568.064,65.866H699.875l-35.428,44.36H603.491Z"/><pathid="line-6"data-name="line"class="cls-30"d="M634.105,57c25.911,0,51.58,8.076,56.087,21.076,4.881,14.075-19.143,28.5-56.083,28.5s-60.966-14.426-56.087-28.5C582.527,65.072,608.194,57,634.105,57Z"/><imageid="icon_home_foshan"x="582"y="17"width="103"height="103"xlink:href="../assets/images/center/home.png"/></g><g id="circle"><pathid="white"class="cls-31"d="M414.057,225.629c96.638,0,183.089,41.729,194.7,100.322C621.763,391.613,533.734,450,417.167,450c-116.623,0-206.208-58.413-195.026-124.044C232.116,267.4,317.339,225.629,414.057,225.629Z"/><pathid="orange_2"class="cls-32"d="M397.666,306.9c63.817,0,120.7,28.166,126.181,67.065,5.811,41.258-50.026,77.528-124.026,77.528-74.041,0-130.915-36.294-126.336-77.528C277.8,335.086,333.819,306.9,397.666,306.9Z"/><pathid="blue"class="cls-33"d="M399.082,284.02c82.745,0,156.818,36,165.9,86.375,10,55.486-64.543,104.544-163.1,104.544-98.607,0-174.539-49.087-166.169-104.544C243.317,320.056,316.275,284.02,399.082,284.02Z"/><pathid="orange_1"class="cls-34"d="M396.909,228.952c111.911,0,212.629,47.606,229.169,115.472,19.27,79.068-85.494,150.425-225.217,150.425-139.785,0-246.6-71.391-229.688-150.425C185.681,276.624,284.878,228.952,396.909,228.952Z"/><imageid="light_o_3"x="520"y="324"width="72"height="92"xlink:href="../assets/images/center/light_0_3.png"/><imageid="light_o_2"x="141"y="261"width="99"height="137"xlink:href="../assets/images/center/light_0_2.png"/><imageid="light_o_1"x="436"y="385"width="99"height="66"xlink:href="../assets/images/center/light_0_1.png"/></g><imageid="center-houes"x="103"y="120"width="539"height="419"xlink:href="../assets/images/center/house.png"/><g id="right"><g id="组_380" data-name="组 380"><pathid="line_b_3"class="cls-35"d="M254.251,93.032s47.68,24.959,35.63,74.5,43.548,85.6,43.548,85.6"/><pathid="line_b_2"class="cls-35"d="M122.023,310.584s19.568,33.927,95.014-1.189,85.512,3.963,85.512,3.963"/><pathid="line_b_1"class="cls-35"d="M236.832,551.912s54.438-25.6,47.506-82.424,34.839-88.368,34.839-88.368"/><pathid="line_o_3"class="cls-36"d="M558.295,108.09s-49.1,12.55-54.633,70.932-39.193,77.669-39.193,77.669"/><pathid="line_o_2"class="cls-36"d="M653,387s-39.424,20.259-79-30-70.444-42.177-79-40"/><pathid="line_o_1"class="cls-36"d="M505,579s-31.47-27.546-17-86c12.415-50.151-42-83-42-83"/><g id="dots_b"><circleid="dots39"class="cls-37"cx="256.219"cy="94.234"r="2.781"/><pathid="dots38"class="cls-38"d="M331.062,248.777a2.766,2.766,0,1,1-2.765,2.766A2.766,2.766,0,0,1,331.062,248.777Z"/><pathid="dots37"class="cls-38"d="M120.828,306.621a2.781,2.781,0,1,1-2.781,2.781A2.781,2.781,0,0,1,120.828,306.621Z"/><circleid="dots36"class="cls-39"cx="300.938"cy="311.781"r="2.781"/><circleid="dots35"class="cls-37"cx="236.422"cy="552.313"r="2.766"/><pathid="dots34"class="cls-38"d="M318.391,380.34a2.766,2.766,0,1,1-2.782,2.765A2.773,2.773,0,0,1,318.391,380.34Z"/><imageid="dots28"x="255"y="91"width="22"height="23"xlink:href="../assets/images/center/dots28.png"/><circleid="dots27"class="cls-40"cx="321.25"cy="243.625"r="2.375"/><circleid="dots26"class="cls-41"cx="288"cy="184.969"r="2.375"/><circleid="dots25"class="cls-42"cx="155.766"cy="326.047"r="2.359"/><circleid="dots24"class="cls-43"cx="284.828"cy="298.703"r="2.359"/><pathid="dots23"class="cls-44"d="M255.547,537.652a2.375,2.375,0,1,1-2.375,2.375A2.375,2.375,0,0,1,255.547,537.652Z"/><pathid="dots22"class="cls-45"d="M285.641,479a2.375,2.375,0,1,1-2.375,2.375A2.375,2.375,0,0,1,285.641,479Z"/><circleid="dots21"class="cls-46"cx="286.813"cy="436.985"r="2.375"/><circleid="dots20"class="cls-47"cx="276.125"cy="112.078"r="1.594"/><pathid="dots19"class="cls-48"d="M291.578,149.308a1.579,1.579,0,1,1-1.594,1.578A1.587,1.587,0,0,1,291.578,149.308Z"/><pathid="dots18"class="cls-49"d="M306.625,226.965a1.594,1.594,0,1,1-1.578,1.593A1.585,1.585,0,0,1,306.625,226.965Z"/><circleid="dots17"class="cls-50"cx="140.734"cy="323.266"r="1.578"/><circleid="dots16"class="cls-51"cx="234.938"cy="302.672"r="1.594"/><circleid="dots15"class="cls-52"cx="284.422"cy="465.516"r="1.578"/><circleid="dots14"class="cls-53"cx="266.625"cy="528.938"r="1.594"/><circleid="dots13"class="cls-54"cx="307.797"cy="393.016"r="1.578"/></g><g id="dots_o"><pathid="dots33"class="cls-55"d="M555.906,103.715a2.766,2.766,0,1,1-2.765,2.765A2.765,2.765,0,0,1,555.906,103.715Z"/><pathid="dots32"class="cls-55"d="M466.437,252.34a2.766,2.766,0,1,1-2.765,2.765A2.765,2.765,0,0,1,466.437,252.34Z"/><circleid="dots31"class="cls-56"cx="652.093"cy="385.89"r="2.781"/><pathid="dots30"class="cls-55"d="M494.937,312.558a2.766,2.766,0,1,1-2.765,2.766A2.766,2.766,0,0,1,494.937,312.558Z"/><circleid="dots29"class="cls-56"cx="505.625"cy="576.485"r="2.781"/><circleid="dots29-2"data-name="dots29"class="cls-56"cx="446.25"cy="409.64"r="2.781"/><use id="dots12" x="516" y="118" xlink:href="#image" /><use id="dots11" x="505" y="304" xlink:href="#image" /><use id="dots10" x="572" y="353" xlink:href="#image" /><use id="dots09" x="486" y="555" xlink:href="#image" /><use id="dots08" x="479" y="465" xlink:href="#image" /><use id="dots07" x="499" y="158" xlink:href="#image-2" /><use id="dots06" x="483" y="221" xlink:href="#image-2" /><use id="dots05" x="470" y="239" xlink:href="#image-2" /><use id="dots04" x="632" y="383" xlink:href="#image-2" /><use id="dots03" x="564" y="346" xlink:href="#image-2" /><use id="dots02" x="455" y="415" xlink:href="#image-2" /><use id="dots01" x="482" y="455" xlink:href="#image-2" /></g><!-- 开始给点制作动画特效 1个点--><!-- <circle cx="0" xy="0" r="3" class="cus-cls-blue"> --><!-- 做动画 --><!-- <animateMotiondur="6s"begin="0s"repeatCount="indefinite"rotate="auto"> --><!-- 沿着哪条线/路径进行 --><!-- <mpath href="#line_b_3"></mpath></animateMotion></circle> --><!-- n个点--左侧 --><template v-for="item in [1, 2, 3]"><circle cx="0" xy="0" r="3" class="cus-cls-blue"><!-- 做动画 --><animateMotiondur="6s"begin="0s"repeatCount="indefinite"rotate="auto"><!-- 沿着哪条线/路径进行 --><mpath :href="`#line_b_${item}`"></mpath></animateMotion></circle><circle cx="0" xy="0" r="3" class="cus-cls-blue"><!-- 做动画 --><animateMotiondur="6s"begin="-3s"repeatCount="indefinite"rotate="auto"><!-- 沿着哪条线/路径进行 --><mpath :href="`#line_b_${item}`"></mpath></animateMotion></circle></template><!-- n个点--右侧 --><template v-for="item in [1, 2, 3]"><circle cx="0" xy="0" r="3" class="cus-cls-orange"><!-- 做动画 --><animateMotiondur="6s"begin="0s"repeatCount="indefinite"rotate="auto"><!-- 沿着哪条线/路径进行 --><mpath :href="`#line_o_${item}`"></mpath></animateMotion></circle><circle cx="0" xy="0" r="3" class="cus-cls-orange"><!-- 做动画 --><animateMotiondur="6s"begin="-3s"repeatCount="indefinite"rotate="auto"><!-- 沿着哪条线/路径进行 --><mpath :href="`#line_o_${item}`"></mpath></animateMotion></circle></template></g></g><g id="text"><textid="text6"class="cls-57"transform="translate(179.049 154.026) scale(0.481 0.481)">广州</text><textid="text5"class="cls-57"transform="translate(63.771 351.7) scale(0.481 0.481)">深圳</text><textid="text4"class="cls-57"transform="translate(161.75 622.618) scale(0.481 0.481)">东莞</text><textid="text3"class="cls-57"transform="translate(583.87 649.734) scale(0.481 0.481)">珠海</text><textid="text2"class="cls-57"transform="translate(719.835 441.012) scale(0.481 0.481)">中山</text><textid="text1"class="cls-57"transform="translate(637.843 173.315) scale(0.481 0.481)">佛山</text></g></g></svg><!-- 烟花特效 --><img class="lingxA" src="../assets/images/ling/lingxA.png" /><img class="lingxB" src="../assets/images/ling/lingxB.png" /><img class="lingxC" src="../assets/images/ling/lingxC.png" /><img class="lingxD" src="../assets/images/ling/lingxD.png" /><img class="lingxE" src="../assets/images/ling/lingxE.png" /><img class="lingxF" src="../assets/images/ling/lingxF.png" /></div>
</template><script setup>
import gsap from "gsap";
import { onMounted } from "vue";onMounted(() => {let timeline = gsap.timeline({});timeline.fromTo("#dongxiao",{duration: 1,scale: 0.8,y: 40,},{duration: 1,scale: 1,y: 0,}).fromTo(["#center-houes"],{duration: 1,opacity: 0.5,scale: 0.7,transformOrigin: "bottom",y: 20,},{duration: 1,opacity: 1,scale: 1,transformOrigin: "bottom",y: 0,},"-=1");
});
</script><style lang="scss" scoped>
.cls-1,
.cls-11,
.cls-12,
.cls-16,
.cls-17,
.cls-2,
.cls-21,
.cls-22,
.cls-26,
.cls-27,
.cls-31,
.cls-6,
.cls-7 {stroke: #fff;
}.cls-1,
.cls-10,
.cls-11,
.cls-12,
.cls-15,
.cls-16,
.cls-17,
.cls-2,
.cls-20,
.cls-21,
.cls-22,
.cls-25,
.cls-26,
.cls-27,
.cls-30,
.cls-31,
.cls-5,
.cls-6,
.cls-7 {stroke-width: 3px;
}.cls-1,
.cls-10,
.cls-11,
.cls-12,
.cls-13,
.cls-14,
.cls-15,
.cls-16,
.cls-17,
.cls-18,
.cls-19,
.cls-2,
.cls-20,
.cls-21,
.cls-22,
.cls-23,
.cls-24,
.cls-25,
.cls-26,
.cls-27,
.cls-28,
.cls-29,
.cls-3,
.cls-30,
.cls-31,
.cls-32,
.cls-33,
.cls-34,
.cls-35,
.cls-36,
.cls-38,
.cls-4,
.cls-44,
.cls-45,
.cls-48,
.cls-49,
.cls-5,
.cls-55,
.cls-6,
.cls-7,
.cls-8,
.cls-9 {fill-rule: evenodd;
}.cls-1,
.cls-11,
.cls-16,
.cls-21,
.cls-26,
.cls-6 {opacity: 0.15;
}.cls-1 {fill: url(#linear-gradient);
}.cls-12,
.cls-13,
.cls-14,
.cls-17,
.cls-18,
.cls-19,
.cls-2,
.cls-22,
.cls-23,
.cls-24,
.cls-27,
.cls-28,
.cls-29,
.cls-3,
.cls-4,
.cls-7,
.cls-8,
.cls-9 {opacity: 0.3;
}.cls-2 {fill: url(#linear-gradient-2);
}.cls-3 {fill: url(#linear-gradient-3);
}.cls-4 {fill: url(#linear-gradient-4);
}.cls-10,
.cls-15,
.cls-20,
.cls-25,
.cls-30,
.cls-31,
.cls-32,
.cls-33,
.cls-34,
.cls-35,
.cls-36,
.cls-5 {fill: none;
}.cls-10,
.cls-15,
.cls-20,
.cls-25,
.cls-30,
.cls-5 {stroke-dasharray: 12 12;opacity: 0.7;
}.cls-5 {stroke: url(#linear-gradient-5);
}.cls-6 {fill: url(#linear-gradient-6);
}.cls-7 {fill: url(#linear-gradient-7);
}.cls-8 {fill: url(#linear-gradient-8);
}.cls-9 {fill: url(#linear-gradient-9);
}.cls-10 {stroke: url(#linear-gradient-10);
}.cls-11 {fill: url(#linear-gradient-11);
}.cls-12 {fill: url(#linear-gradient-12);
}.cls-13 {fill: url(#linear-gradient-13);
}.cls-14 {fill: url(#linear-gradient-14);
}.cls-15 {stroke: url(#linear-gradient-15);
}.cls-16 {fill: url(#linear-gradient-16);
}.cls-17 {fill: url(#linear-gradient-17);
}.cls-18 {fill: url(#linear-gradient-18);
}.cls-19 {fill: url(#linear-gradient-19);
}.cls-20 {stroke: url(#linear-gradient-20);
}.cls-21 {fill: url(#linear-gradient-21);
}.cls-22 {fill: url(#linear-gradient-22);
}.cls-23 {fill: url(#linear-gradient-23);
}.cls-24 {fill: url(#linear-gradient-24);
}.cls-25 {stroke: url(#linear-gradient-25);
}.cls-26 {fill: url(#linear-gradient-26);
}.cls-27 {fill: url(#linear-gradient-27);
}.cls-28 {fill: url(#linear-gradient-28);
}.cls-29 {fill: url(#linear-gradient-29);
}.cls-30 {stroke: url(#linear-gradient-30);
}.cls-31 {opacity: 0.1;
}.cls-32,
.cls-33,
.cls-34 {stroke-width: 4px;
}.cls-32 {stroke: url(#linear-gradient-31);
}.cls-33 {stroke: url(#linear-gradient-32);
}.cls-34 {stroke: url(#linear-gradient-33);
}.cls-35 {stroke: #1374f1;
}.cls-35,
.cls-36 {stroke-width: 2px;opacity: 0.8;
}.cls-36 {stroke: #f97a00;
}.cls-37,
.cls-38,
.cls-39 {fill: #0e68ff;
}.cls-39 {opacity: 0.36;
}.cls-40,
.cls-41,
.cls-42,
.cls-43,
.cls-44,
.cls-45,
.cls-46,
.cls-47,
.cls-48,
.cls-49,
.cls-50,
.cls-51,
.cls-52,
.cls-53,
.cls-54 {fill: #fff;opacity: 0.9;
}/* 编写点的样式--蓝色 */
.cus-cls-blue {fill: #fff;opacity: 0.9;filter: url(#blue-filter-2);/* 告诉浏览器该元素将会改变哪些属性,让浏览器提前做好优化的准备( 比较消耗内存 ) */will-change: opacity;
}
/* 编写点的样式--橙色 */
.cus-cls-orange {fill: #fff;opacity: 0.9;filter: url(#orange-filter-2);/* 告诉浏览器该元素将会改变哪些属性,让浏览器提前做好优化的准备( 比较消耗内存 ) */will-change: opacity;
}.cls-40 {filter: url(#filter);
}.cls-41 {filter: url(#filter-2);
}.cls-42 {filter: url(#filter-3);
}.cls-43 {filter: url(#filter-4);
}.cls-44 {filter: url(#filter-5);
}.cls-45 {filter: url(#filter-6);
}.cls-46 {filter: url(#filter-7);
}.cls-47 {filter: url(#filter-8);
}.cls-48 {filter: url(#filter-9);
}.cls-49 {filter: url(#filter-10);
}.cls-50 {filter: url(#filter-11);
}.cls-51 {filter: url(#filter-12);
}.cls-52 {filter: url(#filter-13);
}.cls-53 {filter: url(#filter-14);
}.cls-54 {filter: url(#filter-15);
}.cls-55,
.cls-56 {fill: #f97a00;
}.cls-57 {font-size: 41.603px;fill: #338ed5;text-anchor: middle;font-family: "Source Han Sans CN";
}/* ICON 悬浮动画特效--开始 */
#icon_star_guangzhou {animation: updown 2.2s ease-in infinite;
}#icon_home_foshan {animation: updown 1.9s ease-in infinite;
}#icon_location_zhongshan {animation: updown 2s ease-in infinite;
}#icon_hot_zhuhai {animation: updown 2s ease-in infinite;
}#icon_earth_dongguan {animation: updown 1.7s ease-in infinite;
}#icon_pie_shenzhen {animation: updown 1.7s ease-in infinite;
}@keyframes updown {0%,100% {transform: translateY(0);}50% {transform: translateY(-10px);}
}
/* ICON 悬浮动画特效--结束 *//*=======城市的灯光效果========*/
/* 广州 */
.center .cls-3,
.center .cls-4,/* 佛山 */
.center .cls-28,
.center .cls-29,/* 中山 */
.center .cls-8,
.center .cls-9,/* 珠海 */
.center .cls-23,
.center .cls-24,/* 东莞 */
.center .cls-18,
.center .cls-19,/* 深圳 */
.center .cls-13,
.center .cls-14 {animation: light-beam 3s linear infinite;opacity: 0.2;
}@keyframes light-beam {0% {opacity: 0;}50% {opacity: 1;}100% {opacity: 0;}
}
/*=======城市的灯光效果========*//* 烟花特效--开始 */
.center-svg {position: relative;
}
.center-svg .lingxA {position: absolute;top: 30%;left: 47%;
}
.center-svg .lingxB {position: absolute;top: 35%;left: 58%;
}
.center-svg .lingxC {position: absolute;top: 40%;left: 40%;
}
.center-svg .lingxD {position: absolute;top: 28%;left: 41%;
}
.center-svg .lingxE {position: absolute;top: 28%;left: 54%;
}
.center-svg .lingxF {position: absolute;top: 40%;left: 53%;
}
.center-svg .lingxA {opacity: 0;animation: lingxA 2s linear infinite;
}
.center-svg .lingxB {opacity: 0;animation: lingxB 2.2s linear infinite;
}
.center-svg .lingxC {opacity: 0;animation: lingxC 1.7s linear infinite;
}
.center-svg .lingxD {opacity: 0;animation: lingxC 2.7s linear infinite;
}
.center-svg .lingxE {opacity: 0;animation: lingxB 1.2s linear infinite;
}
.center-svg .lingxF {opacity: 0;animation: lingxA 1.4s linear infinite;
}
/* 向上移动的烟花 */
@keyframes lingxA {from {transform: translateY(0px);opacity: 1;}60% {opacity: 1;}to {transform: translateY(-160px);opacity: 0;}
}@keyframes lingxB {from {transform: translateY(0px);opacity: 1;}40% {opacity: 1;}60%,to {transform: translateY(-120px);opacity: 0;}
}@keyframes lingxC {from {transform: translateY(0px);opacity: 1;}30% {opacity: 1;}50%,to {transform: translateY(-90px);opacity: 0;}
}
/* 烟花特效--结束 */
</style>

bottom-panle.vue
<template><div class="bottom-content"><template v-for="(item, index) in panelItems" :key="item"><div :class="['item', `panel${item.id}`]"><div class="pan-left"><div class="title">{{ item.title }}</div><!-- 数据动画 --><span :id="`total-num-${item.id}`" class="number">{{item.totalNum}}</span><span class="unit">{{ item.unit }}</span></div><div class="pan-right"><span:class="['triangle', item.isUp ? 'up-triangle' : 'down-triangle']"></span><!-- 数据动画 --><span :id="`percentage-num-${item.id}`" class="percentage">{{item.percentage}}</span></div></div></template></div>
</template><script setup>
import { watch, nextTick } from "vue";
import { CountUp } from "countup.js";const props = defineProps({panelItems: {type: Array,default: function () {return [];},},
});watch(() => props.panelItems, (newV, oldV) => {// 在下一次DOM更新完成之后会回调nextTick(() => {startAnimation(newV)})
})// 数字滚动动画函数
function startAnimation(panelItems = []) {let option1 = {decimalPlaces: 1, // 保留两位小数duration: 1.5, // 持续时长useGrouping: false,  // 是否需要分组}let option2 = {decimalPlaces: 1, // 保留两位小数duration: 1.5, // 持续时长useGrouping: false,  // 是否需要分组suffix: '%', // 后缀}panelItems.forEach(item => {// 数据滚动:CountUp(id选择器或元素对象,数字,配置){  }new CountUp(`total-num-${item.id}`, item.totalNum, option1).start()// 百分比滚动new CountUp(`percentage-num-${item.id}`, item.percentage, option2).start()})
}</script><style scoped lang="scss">
.bottom-content {width: 100%;height: 100%;display: flex;flex-direction: row;align-items: center;/* padding-top: 40px; */
}.bottom-content .item {display: flex;flex-direction: row;justify-content: space-between;align-items: center;margin-top: 60px;flex: 1;height: 100%;padding: 0 10px 0 35px;/* border: 1px solid red; */
}.bottom-content .pan-left {font-size: 16px;color: #ffffff;opacity: 0.8;
}
.bottom-content .pan-left .title {color: white;
}
.bottom-content .pan-left .number {font-size: 36px;font-weight: bold;color: #23aeff;line-height: 60px;
}.bottom-content .pan-left .unit {font-size: 18px;color: #23aeff;
}.bottom-content .pan-right {margin-top: 35px;
}.bottom-content .panel1 .pan-right .up-triangle {display: inline-block;margin-bottom: 4px;width: 0;height: 0;border-bottom: 8px solid #c70013;border-left: 8px solid transparent;border-right: 8px solid transparent;
}
.bottom .panel1 .pan-right .percentage {color: #c70013;
}
.bottom .panel2 .pan-right .up-triangle {display: inline-block;margin-bottom: 4px;width: 0;height: 0;border-bottom: 8px solid #c70013;border-left: 8px solid transparent;border-right: 8px solid transparent;
}
.bottom-content .panel2 .pan-right .percentage {color: #c70013;
}.bottom-content .panel3 .pan-right .down-triangle {display: inline-block;margin-bottom: 1px;width: 0;height: 0;border-top: 8px solid #37a73f;border-left: 8px solid transparent;border-right: 8px solid transparent;
}
.bottom-content .panel3 .pan-right .percentage {color: #37a73f;
}
</style>

water-ball.vue
<template><div class="water-ball"><!-- 波浪icon --><svgversion="1.1"xmlns="https://www.w3.org/2000/svg"xmlns:xlink="https://www.w3.org/1999/xlink"x="0px"y="0px"style="display: none"><symbol id="wave"><pathd="M420,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C514,6.5,518,4.7,528.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H420z"></path><pathd="M420,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C326,6.5,322,4.7,311.5,2.7C304.3,1.4,293.6-0.1,280,0c0,0,0,0,0,0v20H420z"></path><pathd="M140,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C234,6.5,238,4.7,248.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H140z"></path><pathd="M140,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C46,6.5,42,4.7,31.5,2.7C24.3,1.4,13.6-0.1,0,0c0,0,0,0,0,0l0,20H140z"></path></symbol></svg><!-- 水球 --><div class="box" :style="{ width: size, height: size }"><div class="percent" :style="{ fontSize: countSize }"><div class="percentNum" id="count" ref="countRef">0</div><div class="percentB">%</div></div><!-- 这个元素往上移 --><div id="water" class="water" ref="waterRef"><svg viewBox="0 0 560 20" class="water_wave water_wave_back"><use xlink:href="#wave"></use></svg><svg viewBox="0 0 560 20" class="water_wave water_wave_front"><use xlink:href="#wave"></use></svg></div></div></div>
</template><script setup>
import { ref, watch } from "vue";const props = defineProps({size: {type: String,default: "190px",},// 目标进度percentage: {type: Number,default: 0,},countSize: {type: String,default: "40px",},
});const countRef = ref(null);
const waterRef = ref(null);watch(() => props.percentage, (newV, oldV) => {startAnimation(newV)
});// 水球动画函数
function startAnimation(percentage) {let countEl = countRef.value;let waterEl = waterRef.value;let percent = countEl.innerText; // 数据初始值 0let interval;// 1.定时更新数据interval = setInterval(function () {countEl.innerHTML = percent;if (percent <= 100) {// 2.超过100不能移动waterEl.style.transform = "translate(0" + "," + (100 - percent) + "%)";}// 3.停止定时if (percent >= percentage) {countEl.innerHTML = percentage;clearInterval(interval);}percent++;}, 60);
}
</script><style scoped>
.water-ball {position: relative;
}
.box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);border-radius: 100%;overflow: hidden;
}
.box .percent {position: absolute;left: 0;top: 0;z-index: 3;width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;color: #fff;
}
.box .water {position: absolute;left: 0;top: 0;z-index: 2;width: 100%;height: 100%;transform: translate(0, 100%);background: #00c6ff;
}
/* 波浪定位 */
.box .water_wave {width: 200%;position: absolute;bottom: 100%;
}/* ============波浪动画============ */
.box .water_wave_back {right: 0;fill: #c7eeff;animation: wave-back 1.4s infinite linear;
}
.box .water_wave_front {left: 0;fill: #00c6ff;margin-bottom: -1px;animation: wave-front 0.7s infinite linear;
}
@keyframes wave-front {100% {transform: translateX(-50%);}
}
@keyframes wave-back {100% {transform: translateX(50%);}
}
/* ============波浪动画============ */
</style>

right-top-panle.vue
<template><div class="right-top-panel"><!-- 1. 水球 --><water-ball class="right-water-ball" :percentage="percentage"></water-ball><!-- 2. 图例 --><div class="legend"><template v-for="item in panelItems" :key="item"><div class="leg-name"><span :class="['dot', `area${item.id}`]"></span><span class="name">{{ item.name }}</span><span class="percentage">{{ item.percentage }}</span></div></template></div></div>
</template><script setup>
import WaterBall from "./water-ball.vue";const props = defineProps({percentage: {type: Number,default: 0,},panelItems: {type: Array,default: function () {return [];},},
});
</script><style scoped>
.right-top-panel {width: 100%;height: 100%;display: flex;flex-direction: row;align-items: center;
}.right-top-panel .right-water-ball {width: 269px;height: 199px;margin-top: 50px;margin-left: 40px;
}.right-top-panel .legend {flex: 1;
}
.right-top-panel .leg-name {margin-top: 23px;margin-left: 40px;
}
.right-top-panel .leg-name span {display: inline-block;font-size: 20px;margin-right: 11px;
}
.right-top-panel .legend .dot {width: 17px;height: 17px;border-radius: 50%;
}
.right-top-panel .legend .area1 {background-color: #209393;
}
.right-top-panel .legend .area2 {background-color: #1a54a5;
}
.right-top-panel .legend .area3 {background-color: #85caf0;
}
.right-top-panel .legend .area4 {background-color: #f5b64a;
}
.right-top-panel .legend .area5 {background-color: #ee792e;
}
.right-top-panel .legend .name {color: white;
}
.right-top-panel .legend .percentage {color: #0cd2ea;
}
</style>

right-bottom.vue
<template><svgid="yichang"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"width="456"height="127"viewBox="0 0 456 127"><defs><linearGradientid="lwj-linear-gradient"x1="432"y1="61.625"x2="2"y2="61.625"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#26cadd" /><stop offset="0.301" stop-color="#26a3ff" /><stop offset="0.624" stop-color="#26cadd" /><stop offset="0.994" stop-color="#26a3ff" /><stop offset="1" stop-color="#26a3ff" /></linearGradient><linearGradientid="lwj-linear-gradient-2"x1="432"y1="61.625"x2="2"y2="61.625"gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2b6bdc" /><stop offset="0.031" stop-color="#2b6bdc" /><stop offset="0.597" stop-color="#2bdcd2" /><stop offset="1" stop-color="#2b6bdc" /></linearGradient><filter id="lwj-filter" filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#f98800" flood-opacity="0.6" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter><filterid="lwj-filter-2"x="67"y="-6"width="50"height="49"filterUnits="userSpaceOnUse"><feGaussianBlur result="blur" stdDeviation="6.667" in="SourceAlpha" /><feComposite result="composite" /><feComposite result="composite-2" /><feComposite result="composite-3" /><feFlood result="flood" flood-color="#f98800" flood-opacity="0.6" /><feComposite result="composite-4" operator="in" in2="composite-3" /><feBlend result="blend" in2="SourceGraphic" /><feBlend result="blend-2" in="SourceGraphic" /></filter></defs><pathid="curve_right"class="lwj-cls-1"d="M2.006,86.083H31.461l3.006-9.664,4.208,13.288,4.208-10.268,3.006,6.644H73.541l4.208-10.872L83.76,103l7.871-82.748,10.163,71.876,3.607-6.644h11.421l3.607,13.892L124.637,72.8l5.41,20.536,3.006-7.852h46.888l4.208-15.7,6.011,28.388,5.41-19.932,4.208,7.248h37.815L241,76l4,14,5-11,3,6h27l4-11,6,29,10-69,8,57,3-6h13l3,14,4-27,6,20,2-7h46l6-16,5,29,7-20,4,7h25"/><pathid="curve"class="lwj-cls-2"d="M2.006,86.083H31.461l3.006-9.664,4.208,13.288,4.208-10.268,3.006,6.644H73.541l4.208-10.872L83.76,103l7.871-82.748,10.163,71.876,3.607-6.644h11.421l3.607,13.892L124.637,72.8l5.41,20.536,3.006-7.852h46.888l4.208-15.7,6.011,28.388,5.41-19.932,4.208,7.248h37.815L241,76l4,14,5-11,3,6h27l4-11,6,29,10-69,8,57,3-6h13l3,14,4-27,6,20,2-7h46l6-16,5,29,7-20,4,7h25"/><!-- <circleid="curve_d_2"class="lwj-cls-3"cx="299.563"cy="34.734"r="4.813"/><ellipseid="curve_d_1"class="lwj-cls-4"cx="91.578"cy="17.844"rx="4.828"ry="4.844"/> --><!-- 只有一个点 --><!-- <circle  class="lwj-cls-3" cx="0" cy="0" r="5" fill="red"><animateMotiondur="10s"repeatCount="indefinite"rotate="auto"begin="0s"><mpath href="#curve"></mpath></animateMotion></circle> --><!-- n 个点 --><template v-for="(item, index) in dots" :key="item"><circle class="lwj-cls-3" cx="0" cy="0" :r="item.value"><animateMotion:dur="item.dur"repeatCount="indefinite"rotate="auto":begin="item.begin"><mpath href="#curve"></mpath></animateMotion></circle></template></svg>
</template><script setup>
const props = defineProps({dots: {type: Array,default: function () {return [];},},
});
</script><style scoped>
.lwj-cls-1,
.lwj-cls-2 {fill: none;stroke-linecap: round;stroke-linejoin: round;stroke-width: 4px;fill-rule: evenodd;
}.lwj-cls-1 {opacity: 0.8;stroke: url(#lwj-linear-gradient);
}.lwj-cls-2 {stroke: url(#lwj-linear-gradient-2);
}.lwj-cls-3,
.lwj-cls-4 {fill: #f98800;/* 告诉浏览器该元素将会改变哪些属性,让浏览器提前做好优化的准备( 比较消耗内存 ) */will-change: opacity;
}.lwj-cls-3 {filter: url(#lwj-filter);
}.lwj-cls-4 {filter: url(#lwj-filter-2);
}
</style>

在组件中使用

模拟数据

views/config/homeData.js   

// 充电桩数据
export const chargingPileData = [{// value: 100,value: 0,name: "广州占比",// percentage: "5%",percentage: "0%",color: "#34D160",},{// value: 200,value: 0,name: "深圳占比",// percentage: "4%",percentage: "0%",color: "#027FF2",},{// value: 300,value: 0,name: "东莞占比",// percentage: "8%",percentage: "0%",color: "#8A00E1",},{// value: 400,value: 0,name: "佛山占比",// percentage: "10%",percentage: "0%",color: "#F19610",},{// value: 500,value: 0,name: "中山占比",// percentage: "20%",percentage: "0%",color: "#6054FF",},{// value: 600,value: 0,name: "珠海占比",// percentage: "40%",percentage: "0%",color: "#00C6FF",},
];// 流程监控数据
export const precessMonitoringData = [{name: "正常",data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],// data: [220, 182, 191, 234, 290, 330, 310, 201, 154, 190, 330, 410],},{name: "异常",data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],// data: [20, 12, 11, 24, 90, 330, 10, 1, 154, 90, 330, 10],},
];// 充电数据统计
export const chargingStatisticsData = [{name: "一月",value: 0,// value: 500},{name: "二月",value: 0,// value: 2000},{name: "三月",value: 0,// value:  3600},{name: "四月",value: 0,// value: 1000},{name: "五月",value: 0,// value: 1000},{name: "六月",value: 0,// value: 2000},{name: "七月",value: 0,// value: 4000},
];// 异常监控
export const exceptionMonitoringData = [// {//     "id": 1,//     "name": "异常1",//     "value": 5,//     "dur": "10s",//     "begin": "0s"// },// {//     "id": 2,//     "name": "异常2",//     "value": 3,//     "dur": "10s",//     "begin": "-3s"// },// {//     "id": 3,//     "name": "异常3",//     "value": 5,//     "dur": "10s",//     "begin": "-5s"// }
];// 充电桩数据分析
export const dataAnalysisData = [// {//   id: 1,//   title: "充电桩总数(个)",//   totalNum: 8579.9,//   unit: "万",//   percentage: 79.5,//   isUp: true,// },// {//   id: 2,//   title: "年增长总数(个)",//   totalNum: 2856.6,//   unit: "万",//   percentage: 88.9,//   isUp: true,// },// {//   id: 3,//   title: "月增长总数(个)",//   totalNum: 1189.3,//   unit: "万",//   percentage: 62,//   isUp: false,// },{id: 1,title: "充电桩总数(个)",totalNum: 0,unit: "万",percentage: 0,isUp: true,},{id: 2,title: "年增长总数(个)",totalNum: 0,unit: "万",percentage: 0,isUp: true,},{id: 3,title: "月增长总数(个)",totalNum: 0,unit: "万",percentage: 0,isUp: false,},
];// 充电桩Top4占比
export const chargingTop4Data = [{id: 1,name: "深圳",percentage: "0%",},{id: 2,name: "广州",percentage: "0%",},{id: 3,name: "东莞",percentage: "0%",},{id: 4,name: "佛山",percentage: "0%",},{id: 5,name: "其它",percentage: "0%",},// {//   id: 1,//   name: "深圳",//   percentage: "30%",// },// {//   id: 2,//   name: "广州",//   percentage: "20%",// },// {//   id: 3,//   name: "东莞",//   percentage: "10%",// },// {//   id: 4,//   name: "佛山",//   percentage: "10%",// },// {//   id: 5,//   name: "其它",//   percentage: "30%",// },
];

真实请求

views/powerView.vue

<template><main class="screen-bg"><div class="header"></div><div class="left-top"><PieEcharts :echartsChargingPileData="echartsChargingPileData" /></div><div class="left-bottom"><LineEcharts :echartsPrecessMonitoringData="echartsPrecessMonitoringData" /></div><div class="right-top"><RightTopPanel :panelItems="echartChargingTop4Data" :percentage="percentage" /></div><div class="right-center"><BarEchaarts :echartsChargingStatisticsData="echartsChargingStatisticsData" /></div><div class="right-bottom"><RightBottomSvg :dots="echartsExceptionMonitoringData" /></div><div class="center"><CenterSvg /></div><div class="bottom"><BottomPanel :panelItems="echartDataAnalysisData" /></div></main>
</template><script setup>
import PieEcharts from "@/components/pie-echarts.vue";
import LineEcharts from "@/components/line-echarts.vue";
import BarEchaarts from "@/components/bar-echarts.vue"
import {chargingPileData,precessMonitoringData,chargingStatisticsData,exceptionMonitoringData,dataAnalysisData,chargingTop4Data
} from '@/views/config/homeData'
import {getPowerScreenData} from '@/services'
import RightBottomSvg from '@/components/right-bottom-svg.vue'
import CenterSvg from '@/components/center-svg.vue'
import BottomPanel from '@/components/bottom-panel.vue'
import RightTopPanel from '@/components/right-top-panel.vue'import { ref } from "vue";// 充电桩饱和比例数据
let echartsChargingPileData = ref(chargingPileData);// 流程监控数据
let echartsPrecessMonitoringData = ref(precessMonitoringData)// 充电数据统计
let echartsChargingStatisticsData  = ref(chargingStatisticsData)// 异常监控
let echartsExceptionMonitoringData = ref(exceptionMonitoringData)// 充电桩数据分析
let echartDataAnalysisData = ref(dataAnalysisData)// 充电桩TOP4占比
let echartChargingTop4Data = ref(chargingTop4Data)
let percentage = ref(0) // 水球的百分比// 发送网络请求获取数据
getPowerScreenData().then(res => {echartsChargingPileData.value = res.data.chargingPile.dataechartsPrecessMonitoringData.value = res.data.processMonitoring.dataechartsChargingStatisticsData.value = res.data.chargingStatistics.dataechartsExceptionMonitoringData.value = res.data.exceptionMonitoring.dataechartDataAnalysisData.value = res.data.dataAnalysis.dataechartChargingTop4Data.value = res.data.chargingTop4.datapercentage.value = res.data.chargingTop4.totalPercentage
})
</script><style lang="scss" scoped>
.screen-bg {position: absolute;width: 100%;height: 100%;background-image: url(@/assets/images/bg.png);background-repeat: no-repeat;background-size: 100% 100%;background-color: #070a3c;.header {position: absolute;top: 21px;left: 0;right: 0;height: 56px;background-image: url(@/assets/images/bg_header.svg);}.left-top {position: absolute;top: 116px;left: 16px;width: 536px;height: 443px;background-image: url(@/assets/images/bg_left-top.svg);background-repeat: no-repeat;background-size: 100% 100%;}.left-bottom {position: absolute;bottom: 40px;left: 16px;width: 536px;height: 443px;background-image: url(@/assets/images/bg_left_bottom.svg);background-repeat: no-repeat;background-size: 100% 100%;}.right-top {position: absolute;right: 17px;top: 96px;width: 519px;height: 327px;background-image: url(@/assets/images/bg_right_top.svg);background-repeat: no-repeat;background-size: 100% 100%;}.right-center {position: absolute;right: 17px;top: 443px;width: 519px;height: 327px;background-image: url(@/assets/images/bg_right_center.svg);background-repeat: no-repeat;background-size: 100% 100%;}.right-bottom {position: absolute;right: 17px;bottom: 49px;width: 519px;height: 242px;display: flex;justify-content: center;align-items: center;background-image: url(@/assets/images/bg_right_bottom.svg);background-repeat: no-repeat;background-size: 100% 100%;}.center {position: absolute;right: 540px;bottom: 272px;width: 823px;height: 710px;/* border: 5px solid pink; */}.bottom {position: absolute;right: 540px;bottom: 49px;width: 823px;height: 209px;background-image: url(@/assets/images/bg_bottom.svg);background-repeat: no-repeat;background-size: 100% 100%;}
}
</style>

这里如果想进一步优化,比如如何按需引入echarts ,可参考: vue3中如何更优雅的使用echarts?-CSDN博客 片文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/10882.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

宝塔面板怎么解决nginx跨域问题

1.找到宝塔的nginx配置文件 宝塔有一点不同&#xff0c;nginx配置文件不在nginx的安装目录中&#xff0c;应当去/www/server/panel/vhost/nginx找到 2.添加你要跨域的地址 location /api {proxy_pass http://localhost:8080;proxy_set_header Host $host;proxy_set_header X-…

维护祖传项目Tomcat部署war包

文章目录 1. 安装tomcat2. 解决Tomcat启动日志乱码3. idea配置启动war包 1. 安装tomcat 选择免安装版本&#xff0c;只需要在系统变量里面配置一下。 新增系统变量 CATALINA_HOME D:\Users\common\tomcat\apache-tomcat-8.5.97-windows-x64\apache-tomcat-8.5.97 编辑追加Path…

FPGA SDRAM读写控制器

感谢邓堪文大佬 &#xff01; SDRAM 同步动态随机存取内存&#xff08;synchronousdynamic randon-access menory&#xff0c;简称SDRAM&#xff09;是有一个同步接口的动态随机存取内存&#xff08;DRAM&#xff09;。通常DRAM是有一个异步接口的&#xff0c;这样它可以随时响…

Node.js基础:从入门到实战

初识 Node.js 与内置模块 &#xff08;初识&#xff09; 1、知道什么是node.js 2、知道node.js可以做什么 3、node.js 中js的组成部分 &#xff08;内置模块&#xff09; 4、用 fs 模块读写操作文件 5、使用 path 模块处理路径 6、使用http 模块写一个基本的web服务器 初识 N…

设计模式——模板设计模式(Template Method)

模板设计-base 什么是模板&#xff1f; 举个简单的例子&#xff0c;以AABB的格式&#xff0c;写出一个词语&#xff0c;你可能会想到&#xff0c;明明白白&#xff0c;干干净净等&#xff0c; 这个AABB就是一个模板&#xff0c;对模板心中有了一个清晰的概念之后&#xff0c;…

环境变量(全)

概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪里&#xff0c;但是照样可以链接成功&#xff0c;生成可执…

今日arXiv最热NLP大模型论文:揭露大语言模型短板,北京大学提出事件推理测试基准

人工智能领域又一里程碑时刻&#xff01;北京大学、北京智源人工智能研究院等机构联合推出大型事件推理评测基准 。这是首个同时在知识和推理层面全面评估大模型事件推理能力的数据集。 总所周知&#xff0c;事件推理需要丰富的事件知识和强大的推理能力&#xff0c;涉及多种推…

consul启动Error_server_rejoin_age_max (168h0m0s) - consider wiping your data dir

consul 启动报错&#xff1a; consul[11880]: 2024-05-12T08:37:51.095-0400 [ERROR] agent: startup error: error"refusing to rejoin cluster because server has been offline for more than the configured server_rejoin_age_max (168h0m0s) - consider wiping you…

【GD32】02-ADC模拟数字转换器

ADC 在电子和通信技术中&#xff0c;ADC&#xff08;模拟数字转换器&#xff09;是一种将模拟信号转换为数字信号的电子设备。这种转换是电子系统中非常关键的一个环节&#xff0c;因为数字信号更易于处理、存储和传输。ADC的工作原理通常包括采样、保持、量化和编码等步骤。采…

http协议 tomcat如何访问资源 servlet理论介绍

tomcat介绍 bin是启动命令&#xff1b; conf是配置&#xff0c;可以修改端口号&#xff1b; lib是依赖的jar包&#xff1b; logs是日志 webapps是重点&#xff0c;在这里新建我们自己的javaWeb项目 tomcat如何访问资源 tomcat通过统一资源定位符&#xff08;URL&#xff09;来…

乡村振兴与农村基础设施建设:加大农村基础设施建设投入,提升农村公共服务水平,改善农民生产生活条件,构建宜居宜业的美丽乡村

一、引言 乡村振兴是我国现代化进程中的重要战略&#xff0c;而农村基础设施建设则是乡村振兴的基石。随着城市化进程的加快&#xff0c;农村基础设施建设滞后的问题日益凸显&#xff0c;成为制约乡村发展的瓶颈。因此&#xff0c;加大农村基础设施建设投入&#xff0c;提升农…

AI大模型探索之路-训练篇21:Llama2微调实战-LoRA技术微调步骤详解

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

华为OD机试 - 执行任务赚积分 - 动态规划(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷+C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。 一、题目描述 现有 N 个任…

Gradle基础学习(六) 认识任务Task

理解Gradle中的任务 Gradle的构建过程基于任务&#xff08;Task&#xff09;的概念&#xff0c;而每个任务都可以包含一个或多个动作&#xff08;Action&#xff09;。 任务是构建中执行的一些独立的工作单元&#xff0c;例如编译类、创建JAR、生成Javadoc或将存档发布到仓库…

4.5网安学习第四阶段第五周回顾(个人学习记录使用)

本周重点 ①部署域环境&#xff08;Win2008&#xff09; ②域组策略 ③域内信息收集 ④(重点)哈希传递攻击PTH ⑤MS14-068 提权漏洞 ⑥黄金票据伪造 ⑦白银票据伪造 ⑧ZeroLogon (CVE-2020-1472) 漏洞复现 本周主要内容 ①部署域环境&#xff08;Win2008&#xff09;…

【算法】滑动窗口——串联所有单词的子串

今天来以“滑动窗口”的思想来详解一道比较困难的题目——串联所有单词的子串&#xff0c;有需要借鉴即可。 目录 1.题目2.下面是示例代码3.总结 1.题目 题目链接&#xff1a;LINK 这道题如果把每个字符串看成一个字母&#xff0c;就是另外一道中等难度的题目&#xff0c;即&…

不同路径| 和 不同路径||

不同路径| 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xf…

大学生体质测试|基于Springboot+vue的大学生体质测试管理系统设计与实现(源码+数据库+文档)

大学生体质测试管理系统 目录 基于Springboot&#xff0b;vue的大学生体质测试管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 4教师功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算…

C++笔试强训day20

目录 1.经此一役小红所向无敌 2.连续子数组最大和 3.非对称之美 1.经此一役小红所向无敌 链接 简单模拟即可。 需要注意的是&#xff1a; 除完之后有无余数&#xff0c;若有&#xff0c;则还可以再挨一次打。 #include <iostream> using namespace std; #define in…

设计模式——结构型模式——代理模式(静态代理、动态代理:JDK、CGLIB)

目录 代理模式 代理模式简介 代理模式的分类 代理模式组成 代理模式的优缺点 静态代理 背景前置 编写代码 JDK动态代理 编写代码 使用Arthas分析JDK动态代理底层原理 CGLIB动态代理 编写代码 三种代理的对比 代理模式使用场景 代理模式 代理模式简介 代理模式属…