在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.rhkb.cn/news/325544.html

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

相关文章

蓝桥杯-网络安全比赛(6) 模拟实验 Metasploit 控制并获取Windows 登录HASH、LM Hash和NTLM Hash密文解析

窃取WINDOWS账号密码 系统环境&#xff1a;主机&#xff08;Windows系统 IP&#xff1a;192.168.126.129)&#xff0c;虚拟机&#xff08;KALI系统 IP&#xff1a;192.168.126.3&#xff09;&#xff0c;两者需要能通过本地网络互通互连。 攻击工具&#xff1a;Metasploit是一…

基于EBAZ4205矿板的图像处理:12图像二值化(阈值可调)

基于EBAZ4205矿板的图像处理&#xff1a;12图像二值化(阈值可调) 我的项目是基于EBAZ4205矿板的阈值可调的图像阈值二值化处理&#xff0c;可以通过按键调整二值化的阈值&#xff0c;key1为阈值加1&#xff0c;key4为阈值减1&#xff0c;key2为阈值加10&#xff0c;key5为阈值…

java项目之校园失物招领系统(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的校园失物招领系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 校园失物招领系统的主要…

如何更好地使用Kafka? - 运行监控篇

要确保Kafka在使用过程中的稳定性&#xff0c;需要从kafka在业务中的使用周期进行依次保障。主要可以分为&#xff1a;事先预防&#xff08;通过规范的使用、开发&#xff0c;预防问题产生&#xff09;、运行时监控&#xff08;保障集群稳定&#xff0c;出问题能及时发现&#…

LLaMA 羊驼系大语言模型的前世今生

关于 LLaMA LLaMA是由Meta AI发布的大语言系列模型&#xff0c;完整的名字是Large Language Model Meta AI&#xff0c;直译&#xff1a;大语言模型元AI。Llama这个单词本身是指美洲大羊驼&#xff0c;所以社区也将这个系列的模型昵称为羊驼系模型。 Llama、Llama2 和 Llama3…

前端笔记-day02

文章目录 01-无序列表02-有序列表03-定义列表04-表格06-表格-合并单元格07-表单-input08-表单-input占位文本09-表单-单选框10-表单-上传多个文件11-表单-多选框12-表单-下拉菜单13-表单-文本域14-表单-label标签15-表单-按钮16-无语义-span和div17-字体实体19-注册登录页面 01…

2024中国(重庆)无人机展览会8月在重庆举办

2024中国(重庆)无人机展览会8月在重庆举办 邀请函 主办单位&#xff1a; 中国航空学会 重庆市南岸区人民政府 招商执行单位&#xff1a; 重庆港华展览有限公司 报名&#xff1a;【交易会I 59交易会2351交易会9466】 展会背景&#xff1a; 为更好的培养航空航天产业和无人…

基于STM32的IIC通信

IIC通信 • I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线 • 两根通信线&#xff1a;SCL&#xff08;串行时钟线&#xff09;、SDA&#xff08;串行数据线&#xff09; • 同步&#xff0c;半双工 • 带数据应答 • 支持总线挂载多…

maven远程仓库访问顺序

首先需要了解一下各个配置文件&#xff0c;主要分为三类&#xff1a; 全局配置文件(${maven.home}/conf/settings.xml)&#xff0c;maven安装路径下的/conf/settings.xml用户配置文件(%USER_HOME%/.m2/settings.xml)&#xff0c;windows用户文件夹下项目配置文件&#xff1a;p…

不错的招聘时候要注意的知识

来自《行为心理学在团队管理中的应用》行为心理学在团队管理中的应用_哔哩哔哩_bilibili

Docker 怎么将映射出的路径设置为非root用户权限

在Docker中&#xff0c;容器的根文件系统默认是由root用户拥有的。如果想要在映射到宿主机的路径时设置为非root用户权限&#xff0c;可以通过以下几种方式来实现&#xff1a; 1. 使用具有特定UID和GID的非root用户运行容器&#xff1a; 在运行容器时&#xff0c;你可以使用-u…

基于ChatGLM+Langchain离线搭建本地知识库(免费)

目录 简介 服务部署 实现本地知识库 测试 番外 简介 ChatGLM-6B是清华大学发布的一个开源的中英双语对话机器人。基于 General Language Model (GLM) 架构&#xff0c;具有 62 亿参数。结合模型量化技术&#xff0c;用户可以在消费级的显卡上进行本地部署&#xff08;INT…

【C/C++】内存分布

本文第一部分主要介绍了程序内存区域的划分以及数据的存储。第二部分有一段代码和一些题目&#xff0c;全面直观得分析了程序中的数组在内存中的存储。 因为不同的数据有不同的存储需求&#xff0c;各区域满足不同的需求&#xff0c;所以程序内存会有区域的划分。 根据需求的不…

【活动】如何通过AI技术提升内容生产的效率与质量

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 如何通过AI技术提升内容生产的效率与质量引言一、自然语言处理&#xff08;NLP&…

Java设计模式 _结构型模式_外观模式

一、外观模式 1、外观模式 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型模式。主要特点为隐藏系统的复杂性&#xff0c;并向客户端提供了一个客户端可以访问系统的接口。这有助于降低系统的复杂性&#xff0c;提高可维护性。当客户端与多个子系统之间存在大量…

Golang | Leetcode Golang题解之第78题子集

题目&#xff1a; 题解&#xff1a; func subsets(nums []int) (ans [][]int) {set : []int{}var dfs func(int)dfs func(cur int) {if cur len(nums) {ans append(ans, append([]int(nil), set...))return}set append(set, nums[cur])dfs(cur 1)set set[:len(set)-1]df…

SpringAMQP Work Queue 工作队列

消息模型: 代码模拟: 相较于之前的基础队列&#xff0c;该队列新增了消费者 不再是一个&#xff0c;所以我们通过代码模拟出两个consumer消费者。在原来的消费者类里写两个方法 其中消费者1效率高 消费者2效率低 RabbitListener(queues "simple.queue")public voi…

Java设计模式-工厂

Java设计模式中&#xff0c;工厂模式主要包括普通工厂模式以及抽象工厂模式&#xff0c;普通工厂模式是用于制造输出不同类型的对象&#xff0c;抽象工厂模式是用于制造输出不同类型的普通工厂&#xff0c;本文主要描述工厂模式的基本用法。 如上所示&#xff0c;使用普通工厂模…

某票星球网图标点选验证码YOLOV8识别案例

注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架 图标点选验证码大家都不陌生了,我们来看下数据集 引言与个人想法 先说结论,本文采用的方法能够达到99的准确率,效果图如下 做图标点选其实方法有很多,有的…

鸿蒙 @builder 使用中的问题

在所有条件都相同的情况下&#xff0c;点击左边的 list更新右侧的list 方案一 使用builder &#xff0c;右侧 list不会更新 方案二 直接写 list UI&#xff0c;右侧list会更新 所以&#xff0c;builder中的数据&#xff0c;无法双向绑定么 BuildergetTreeItemLayout(currentL…