因为要实现的饼图效果较复杂,所以,需要重新写列表。

点击右侧列表的圆点,实现隐藏左侧饼图相应环状。
- <template>
- <div class="index_div">
- <a-spin :spinning="aLoading">
- <scalescreen
- :width="1920"
- :height="1080"
- :selfAdaption="true"
- class="scale-wrap"
- >
- <div class="pieMulBox">
- <div class="pieMulChart">
- <div class="pie_mul_box">
- <div class="innPieBg">
- <div class="number">{{curStorageRate}}</div>
- </div>
- <div class="pieChart">
- <pie_mul ref="pie_mul" />
- </div>
- </div>
- <p style="margin-top: 17px;">当前系统访问率</p>
- </div>
-
- <div class="pieMulMsg">
- <ul>
- <li v-for="(item,index) in pieMulData" :key="index" @click="clickPiechart(item, index)">
- <span>{{item.label}}</span><strong>{{item.value}}</strong>
- </li>
- </ul>
- </div>
-
- </div>
-
- </scalescreen>
- </a-spin>
- </div>
- </template>
-
- <script>
- import { deepClone } from '@/utils/util'
- import pie_mul from './Analysis/pie_mul'
- import scalescreen from './Analysis/scale-screen.vue'
- import { energyStateAnalysis } from '@/api/analysis/index'
-
-
- export default {
- name: "Analysis",
- components: {
- pie_mul,
- scalescreen
- },
- data() {
- return {
- aLoading: true,
- pieMulData: [],
- hidePieData: [], // 点击隐藏的值
- showPieData: [] // 点击显示的值
-
- }
- },
- created() {
- this.getEnergyStateAnalysis()
- setTimeout(()=>{
- this.aLoading = false
- }, 3000)
- },
- methods: {
-
- getEnergyStateAnalysis() {
- energyStateAnalysis().then((res) => {
- // console.log('energyStateAnalysis', res)
- if (res.success) {
- let data = res.result
- this.curStorageRate = data.curStorageRate
-
- // let dataList = [
- // { value: 62.2, label: "小1" },
- // { value: 17.3, label: "基1" },
- // { value: 6.2, label: "移1" },
- // { value: 9.1, label: "农1" },
- // { value: 3.2, label: "三1" },
- // ];
- // this.pieMulData = dataList
- // this.$refs.pie_mul.draw(dataList);
-
- if(data.list && data.list.length > 0) {
- let dataList = []
- this.$nextTick(() => {
- data.list.map(v=>{
- dataList.push({ value: v.cnt, label: v.itemName })
- });
- this.pieMulData = dataList
- this.showPieData = deepClone(dataList)
- this.$refs.pie_mul.draw(dataList);
- })
- }
-
- }
- })
- },
- // 点击饼图旁边的列表,显示和隐藏饼图数据。
- clickPiechart(item, idx) {
- const index = this.hidePieData.indexOf(item.label);
- if (index > -1) {
- this.hidePieData.splice(index, 1);
- this.showPieData[idx] = item
- } else {
- this.hidePieData.push(item.label);
- this.showPieData[idx] = {}
- }
- this.$refs.pie_mul.draw(this.showPieData);
- },
-
- }
- }
- </script>
-
- <style scoped lang="less">
- .index_div {
- margin: -12px -12px 0;
- padding: 12px 12px 0;
- background: #01091D;
- }
- ul, li {
- list-style: none none outside;
- padding: 0;
- margin-bottom: 0;
- }
- .pieMulBox {
- display: flex;
- flex-direction: row;
- padding-left: 12px;
- .pieMulChart {
- text-align: center;
- .pie_mul_box {
- position: relative;
- width: 150px;
- height: 150px;
- border: 3px solid rgba(14, 98, 121, 0.3);
- border-radius: 1000px;
- display: flex;
- align-items: center;
- justify-content: center;
-
- &::before {
- content: '';
- display: block;
- width: 7px;
- height: 7px;
- background: #3AB9FC;
- border-radius: 1000px;
- position: absolute;
- top: -4px;
- left: 68px;
- }
- &::after {
- content: '';
- display: block;
- width: 7px;
- height: 7px;
- background: #3AB9FC;
- border-radius: 1000px;
- position: absolute;
- bottom: -4px;
- left: 68px;
- }
- .pieChart {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .innPieBg {
- width: 93px;
- height: 93px;
- border: 6px solid rgba(14, 98, 121, 0.1);
- border-radius: 1000px;
- position: relative;
-
- .number {
- font-family: Alibaba-PuHuiTi, Alibaba-PuHuiTi;
- font-weight: normal;
- font-size: 26px;
- color: #FFFFFF;
- line-height: 35px;
- text-align: center;
- font-style: normal;
- position: absolute;
- left: 0;
- top: 21px;
- right: 0;
- bottom: 0;
- z-index: 9;
- }
- }
- }
- p {
- font-family: PingFangSC, PingFang SC;
- font-weight: 400;
- font-size: 18px;
- color: #F0F0F0;
- line-height: 25px;
- }
- }
- .pieMulMsg {
- margin-left: 68px;
- padding-top: 19px;
- ul {
- li {
- position: relative;
- padding-left: 23px;
- padding-bottom: 6px;
- margin-bottom: 12px;
-
- &::before {
- content: '';
- display: inline-block;
- width: 8px;
- height: 8px;
- border-radius: 1000px;
- position: absolute;
- left: 0;
- top: 6px;
- }
-
- &::after {
- content: '';
- display: inline-block;
- width: 118px;
- height: 1px;
- background: linear-gradient( 90deg, #0E7FC8 0%, rgba(9,159,216,0.16) 100%);
- box-shadow: 0px 20px 11px 11px rgba(0,21,38,0.01);
- opacity: 0.5;
- position: absolute;
- left: 20px;
- bottom: 0;
- }
-
- &:nth-child(1)::before { background: linear-gradient( 180deg, #469C94 0%, #6AE6C8 100%) }
- &:nth-child(2)::before { background: linear-gradient( 180deg, #21C5F5 0%, #043748 100%) }
- &:nth-child(3)::before { background: linear-gradient( 180deg, #23A9FF 0%, #0321BD 100%) }
- &:nth-child(4)::before { background: linear-gradient( 180deg, #FF7500 0%, #FF7500 100%) }
- &:nth-child(5)::before { background: linear-gradient( 180deg, #a72a21 0%, #803d37 100%) }
- &:nth-child(6)::before { background: linear-gradient( 180deg, #7b0488 0%, #3c1e69 100%) }
- &:nth-child(7)::before { background: linear-gradient( 180deg, #ff00bf 0%, #651754 100%) }
- span {
- display: inline-block;
- width: 110px;
- font-family: PingFangSC, PingFang SC;
- font-weight: 400;
- font-size: 16px;
- color: rgba(255,255,255,0.8);
- line-height: 22px;
- }
- strong {
- font-weight: normal;
- font-size: 18px;
- color: #FFFFFF;
- line-height: 19px;
- }
- }
- }
- }
- }
-
- </style>
echarts的饼图组件:pie_mul.vue
- <template>
- <div class="bg">
- <div id="mulPieChart" style="width: 150px;height:150px;"></div>
- </div>
- </template>
-
- <script>
- // import * as echarts from 'echarts';
-
- // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
- import * as echarts from 'echarts/core';
- // 引入图表,图表后缀都为 Chart
- // import { LineChart } from 'echarts/charts';
- // import { BarChart } from 'echarts/charts';
- // import { CustomChart } from 'echarts/charts';
- import { PieChart } from 'echarts/charts';
- // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
- import {
- // TitleComponent,
- TooltipComponent,
- GridComponent,
- DatasetComponent,
- TransformComponent,
- // MarkLineComponent,
- // MarkAreaComponent,
- // MarkPointComponent
- } from 'echarts/components';
- // 标签自动布局、全局过渡动画等特性
- import { LabelLayout, UniversalTransition } from 'echarts/features';
- // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
- import { CanvasRenderer } from 'echarts/renderers';
-
- // 注册必须的组件
- echarts.use([
- // TitleComponent,
- TooltipComponent,
- GridComponent,
- DatasetComponent,
- TransformComponent,
- // MarkLineComponent,
- // MarkAreaComponent,
- // MarkPointComponent,
- // LineChart,
- // BarChart,
- // CustomChart,
- PieChart,
- LabelLayout,
- UniversalTransition,
- CanvasRenderer
- ]);
-
- export default {
- data() {
- return {
- status: 'loading',
- loading: true,
- chart: null
- }
- },
- created() {
-
- },
- mounted() {
-
- },
- beforeDestroy() {
-
- },
- methods: {
- draw(sourceData) {
- // console.log(sourceData)
- // 基于准备好的dom,初始化echarts实例
- if (!this.chart) {
- this.chart = echarts.init(document.getElementById('mulPieChart'));
- }
-
- // 指定图表的配置项和数据
- let option = {
- tooltip: {
- trigger: 'item'
- },
- series: [
- {
- type: 'pie',
- name: '',
- radius: [55, 62],
- legendHoverLink: false,
- avoidLabelOverlap: false,
- selectedOffset: 0,
- padAngle: 2,
- itemStyle: {
- borderRadius: 2
- },
- label: {
- show: true,
- position: 'center'
- },
- emphasis: {
- label: {
- show: false,
- fontSize: 40,
- fontWeight: 'bold'
- }
- },
- labelLine: {
- show: false
- },
- data: sourceData,
- itemStyle: {
- normal: {
- color: function (params) {
- var colorList = [
- ['#469C94', '#6AE6C8'],
- ['#21C5F5', '#043748'],
- ['#23A9FF', '#0321BD'],
- ['#FF7500', '#FF7500'],
- ['#a72a21', '#803d37'],
- ['#7b0488', '#3c1e69'],
- ['#ff00bf', '#651754'],
- ];
- var index = params.dataIndex;
- return new echarts.graphic.LinearGradient(0, 0, 1, 1, [
- {
- offset: 0,
- color: colorList[index][0]
- },
- {
- offset: 1,
- color: colorList[index][1]
- }
- ]);
- }
- }
- }
- }
- ]
- }
-
- this.chart.setOption(option)
- }
- }
- }
- </script>
-
- <style lang="scss" scoped>
- </style>
-
scale-screen.vue
- <template>
- <div class="screen-wrapper" :class="{'opacity': opacity}" ref="screenWrapper" :style="wrapperStyle">
- <slot></slot>
- </div>
- </template>
- <script>
-
- /**
- * 防抖函数
- * @param {T} fn
- * @param {number} delay
- * @return
- */
- function debounce(fn, delay) {
- let timer = null;
- return function (...args) {
- timer = setTimeout(
- () => {
- typeof fn === "function" && fn.apply(null, args);
- clearTimeout(timer);
- },
- delay > 0 ? delay : 100
- );
- };
- }
-
- export default {
- name: "VScaleScreen",
- props: {
- width: {
- type: [String, Number],
- default: 1920,
- },
- height: {
- type: [String, Number],
- default: 1080,
- },
- fullScreen: {
- type: Boolean,
- default: false,
- },
- autoScale: {
- type: [Object, Boolean],
- default: true,
- },
- selfAdaption: {
- type: Boolean,
- default: true,
- },
- delay: {
- type: Number,
- default: 500,
- },
- boxStyle: {
- type: Object,
- default: () => ({}),
- },
- wrapperStyle: {
- type: Object,
- default: () => ({}),
- },
- },
- data() {
- return {
- currentWidth: 0,
- currentHeight: 0,
- originalWidth: 0,
- originalHeight: 0,
- onResize: null,
- observer: null,
- opacity: false
- };
- },
- watch: {
- selfAdaption(val) {
- if (val) {
- this.resize();
- this.addListener();
- } else {
- this.clearListener();
- this.clearStyle();
- }
- },
- },
- computed: {
- screenWrapper() {
- return this.$refs["screenWrapper"];
- },
- },
- methods: {
- initSize() {
- return new Promise((resolve, reject) => {
- // console.log("初始化样式");
- //给父元素设置 overflow:hidden
- this.screenWrapper.parentNode.style.overflow = "hidden";
- this.screenWrapper.parentNode.scrollLeft = 0;
- this.screenWrapper.parentNode.scrollTop = 0;
-
- this.$nextTick(() => {
- // region 获取大屏真实尺寸
- if (this.width && this.height) {
- this.currentWidth = this.width;
- this.currentHeight = this.height;
- } else {
- this.currentWidth = this.screenWrapper.clientWidth;
- this.currentHeight = this.screenWrapper.clientHeight;
- }
- // endregion
- // region 获取画布尺寸
- if (!this.originalHeight || !this.originalWidth) {
- this.originalWidth = window.screen.width;
- this.originalHeight = window.screen.height;
- }
- // endregion
- resolve();
- });
- });
- },
- updateSize() {
- if (this.currentWidth && this.currentHeight) {
- this.screenWrapper.style.width = `${this.currentWidth}px`;
- this.screenWrapper.style.height = `${this.currentHeight}px`;
- } else {
- this.screenWrapper.style.width = `${this.originalWidth}px`;
- this.screenWrapper.style.height = `${this.originalHeight}px`;
- }
- },
- handleAutoScale(scale) {
- if (!this.autoScale) return;
- const screenWrapper = this.screenWrapper;
- const domWidth = screenWrapper.clientWidth;
- const domHeight = screenWrapper.clientHeight;
- const currentWidth = document.body.clientWidth - 232;
- const currentHeight = document.body.clientHeight - 111;
- screenWrapper.style.transform = `scale(${scale},${scale}) `;
- let mx = Math.max((currentWidth - domWidth * scale) / 2, 0);
- let my = Math.max((currentHeight - domHeight * scale) / 2, 0);
- if (typeof this.autoScale === "object") {
- // @ts-ignore
- !this.autoScale.x && (mx = 0);
- // @ts-ignore
- !this.autoScale.y && (my = 0);
- }
- this.screenWrapper.parentNode.style.height = (this.height * scale) + 'px'
- setTimeout(() => {
- this.opacity = true
- }, 500)
- },
- updateScale() {
- const screenWrapper = this.screenWrapper;
- // 获取真实视口尺寸
- const currentWidth = document.body.clientWidth - 232;
- const currentHeight = document.body.clientHeight - 111;
- // 获取大屏最终的宽高onResize
- const realWidth = this.currentWidth || this.originalWidth;
- const realHeight = this.currentHeight || this.originalHeight;
- // 计算缩放比例
- const widthScale = currentWidth / realWidth;
- const heightScale = currentHeight / realHeight;
- // console.log({currentWidth, currentHeight,realWidth,realHeight});
- // 若要铺满全屏,则按照各自比例缩放
- if (this.fullScreen) {
- screenWrapper.style.transform = `scale(${widthScale},${heightScale})`;
- return false;
- }
- // 按照宽高最小比例进行缩放
- const scale = Math.max(widthScale, heightScale);
- this.handleAutoScale(scale);
- },
- initMutationObserver() {
- const screenWrapper = this.screenWrapper;
- const observer = (this.observer = new MutationObserver(() => {
- this.onResize();
- }));
-
- observer.observe(screenWrapper, {
- attributes: true,
- attributeFilter: ["style"],
- attributeOldValue: true,
- });
- },
- clearListener() {
- window.removeEventListener("resize", this.onResize);
- },
- addListener() {
- window.addEventListener("resize", this.onResize);
- },
- clearStyle() {
- const screenWrapper = this.screenWrapper;
- screenWrapper.parentNode.style.overflow = "auto";
- screenWrapper.style = "";
- },
- async resize() {
- if (!this.selfAdaption) {
- return;
- }
- await this.initSize();
- this.updateSize();
- this.updateScale();
- },
- },
- mounted() {
- this.onResize = debounce(() => {
- this.resize();
- }, this.delay);
- this.$nextTick(() => {
- if (this.selfAdaption) {
- this.resize();
- this.addListener();
- }
- });
- },
- beforeDestroy() {
- this.clearListener();
- },
- };
- </script>
-
- <style scoped>
- .screen-box {
- overflow: hidden;
- background-size: 100% 100%;
- background: #000;
- width: 100vw;
- height: 100vh;
- }
-
- .screen-wrapper {
- transition-property: all;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 500ms;
- position: relative;
- overflow: hidden;
- z-index: 100;
- transform-origin: left top;
- opacity: 0;
- }
-
- .opacity {
- opacity: 1;
- }
- </style>