• 隐藏饼图的legend,重写legend列表。


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

    点击右侧列表的圆点,实现隐藏左侧饼图相应环状。

    1. <template>
    2. <div class="index_div">
    3. <a-spin :spinning="aLoading">
    4. <scalescreen
    5. :width="1920"
    6. :height="1080"
    7. :selfAdaption="true"
    8. class="scale-wrap"
    9. >
    10. <div class="pieMulBox">
    11. <div class="pieMulChart">
    12. <div class="pie_mul_box">
    13. <div class="innPieBg">
    14. <div class="number">{{curStorageRate}}</div>
    15. </div>
    16. <div class="pieChart">
    17. <pie_mul ref="pie_mul" />
    18. </div>
    19. </div>
    20. <p style="margin-top: 17px;">当前系统访问率</p>
    21. </div>
    22. <div class="pieMulMsg">
    23. <ul>
    24. <li v-for="(item,index) in pieMulData" :key="index" @click="clickPiechart(item, index)">
    25. <span>{{item.label}}</span><strong>{{item.value}}</strong>
    26. </li>
    27. </ul>
    28. </div>
    29. </div>
    30. </scalescreen>
    31. </a-spin>
    32. </div>
    33. </template>
    34. <script>
    35. import { deepClone } from '@/utils/util'
    36. import pie_mul from './Analysis/pie_mul'
    37. import scalescreen from './Analysis/scale-screen.vue'
    38. import { energyStateAnalysis } from '@/api/analysis/index'
    39. export default {
    40. name: "Analysis",
    41. components: {
    42. pie_mul,
    43. scalescreen
    44. },
    45. data() {
    46. return {
    47. aLoading: true,
    48. pieMulData: [],
    49. hidePieData: [], // 点击隐藏的值
    50. showPieData: [] // 点击显示的值
    51. }
    52. },
    53. created() {
    54. this.getEnergyStateAnalysis()
    55. setTimeout(()=>{
    56. this.aLoading = false
    57. }, 3000)
    58. },
    59. methods: {
    60. getEnergyStateAnalysis() {
    61. energyStateAnalysis().then((res) => {
    62. // console.log('energyStateAnalysis', res)
    63. if (res.success) {
    64. let data = res.result
    65. this.curStorageRate = data.curStorageRate
    66. // let dataList = [
    67. // { value: 62.2, label: "小1" },
    68. // { value: 17.3, label: "基1" },
    69. // { value: 6.2, label: "移1" },
    70. // { value: 9.1, label: "农1" },
    71. // { value: 3.2, label: "三1" },
    72. // ];
    73. // this.pieMulData = dataList
    74. // this.$refs.pie_mul.draw(dataList);
    75. if(data.list && data.list.length > 0) {
    76. let dataList = []
    77. this.$nextTick(() => {
    78. data.list.map(v=>{
    79. dataList.push({ value: v.cnt, label: v.itemName })
    80. });
    81. this.pieMulData = dataList
    82. this.showPieData = deepClone(dataList)
    83. this.$refs.pie_mul.draw(dataList);
    84. })
    85. }
    86. }
    87. })
    88. },
    89. // 点击饼图旁边的列表,显示和隐藏饼图数据。
    90. clickPiechart(item, idx) {
    91. const index = this.hidePieData.indexOf(item.label);
    92. if (index > -1) {
    93. this.hidePieData.splice(index, 1);
    94. this.showPieData[idx] = item
    95. } else {
    96. this.hidePieData.push(item.label);
    97. this.showPieData[idx] = {}
    98. }
    99. this.$refs.pie_mul.draw(this.showPieData);
    100. },
    101. }
    102. }
    103. </script>
    104. <style scoped lang="less">
    105. .index_div {
    106. margin: -12px -12px 0;
    107. padding: 12px 12px 0;
    108. background: #01091D;
    109. }
    110. ul, li {
    111. list-style: none none outside;
    112. padding: 0;
    113. margin-bottom: 0;
    114. }
    115. .pieMulBox {
    116. display: flex;
    117. flex-direction: row;
    118. padding-left: 12px;
    119. .pieMulChart {
    120. text-align: center;
    121. .pie_mul_box {
    122. position: relative;
    123. width: 150px;
    124. height: 150px;
    125. border: 3px solid rgba(14, 98, 121, 0.3);
    126. border-radius: 1000px;
    127. display: flex;
    128. align-items: center;
    129. justify-content: center;
    130. &::before {
    131. content: '';
    132. display: block;
    133. width: 7px;
    134. height: 7px;
    135. background: #3AB9FC;
    136. border-radius: 1000px;
    137. position: absolute;
    138. top: -4px;
    139. left: 68px;
    140. }
    141. &::after {
    142. content: '';
    143. display: block;
    144. width: 7px;
    145. height: 7px;
    146. background: #3AB9FC;
    147. border-radius: 1000px;
    148. position: absolute;
    149. bottom: -4px;
    150. left: 68px;
    151. }
    152. .pieChart {
    153. position: absolute;
    154. left: 0;
    155. top: 0;
    156. right: 0;
    157. bottom: 0;
    158. display: flex;
    159. align-items: center;
    160. justify-content: center;
    161. }
    162. .innPieBg {
    163. width: 93px;
    164. height: 93px;
    165. border: 6px solid rgba(14, 98, 121, 0.1);
    166. border-radius: 1000px;
    167. position: relative;
    168. .number {
    169. font-family: Alibaba-PuHuiTi, Alibaba-PuHuiTi;
    170. font-weight: normal;
    171. font-size: 26px;
    172. color: #FFFFFF;
    173. line-height: 35px;
    174. text-align: center;
    175. font-style: normal;
    176. position: absolute;
    177. left: 0;
    178. top: 21px;
    179. right: 0;
    180. bottom: 0;
    181. z-index: 9;
    182. }
    183. }
    184. }
    185. p {
    186. font-family: PingFangSC, PingFang SC;
    187. font-weight: 400;
    188. font-size: 18px;
    189. color: #F0F0F0;
    190. line-height: 25px;
    191. }
    192. }
    193. .pieMulMsg {
    194. margin-left: 68px;
    195. padding-top: 19px;
    196. ul {
    197. li {
    198. position: relative;
    199. padding-left: 23px;
    200. padding-bottom: 6px;
    201. margin-bottom: 12px;
    202. &::before {
    203. content: '';
    204. display: inline-block;
    205. width: 8px;
    206. height: 8px;
    207. border-radius: 1000px;
    208. position: absolute;
    209. left: 0;
    210. top: 6px;
    211. }
    212. &::after {
    213. content: '';
    214. display: inline-block;
    215. width: 118px;
    216. height: 1px;
    217. background: linear-gradient( 90deg, #0E7FC8 0%, rgba(9,159,216,0.16) 100%);
    218. box-shadow: 0px 20px 11px 11px rgba(0,21,38,0.01);
    219. opacity: 0.5;
    220. position: absolute;
    221. left: 20px;
    222. bottom: 0;
    223. }
    224. &:nth-child(1)::before { background: linear-gradient( 180deg, #469C94 0%, #6AE6C8 100%) }
    225. &:nth-child(2)::before { background: linear-gradient( 180deg, #21C5F5 0%, #043748 100%) }
    226. &:nth-child(3)::before { background: linear-gradient( 180deg, #23A9FF 0%, #0321BD 100%) }
    227. &:nth-child(4)::before { background: linear-gradient( 180deg, #FF7500 0%, #FF7500 100%) }
    228. &:nth-child(5)::before { background: linear-gradient( 180deg, #a72a21 0%, #803d37 100%) }
    229. &:nth-child(6)::before { background: linear-gradient( 180deg, #7b0488 0%, #3c1e69 100%) }
    230. &:nth-child(7)::before { background: linear-gradient( 180deg, #ff00bf 0%, #651754 100%) }
    231. span {
    232. display: inline-block;
    233. width: 110px;
    234. font-family: PingFangSC, PingFang SC;
    235. font-weight: 400;
    236. font-size: 16px;
    237. color: rgba(255,255,255,0.8);
    238. line-height: 22px;
    239. }
    240. strong {
    241. font-weight: normal;
    242. font-size: 18px;
    243. color: #FFFFFF;
    244. line-height: 19px;
    245. }
    246. }
    247. }
    248. }
    249. }
    250. </style>

    echarts的饼图组件:pie_mul.vue 

    1. <template>
    2. <div class="bg">
    3. <div id="mulPieChart" style="width: 150px;height:150px;"></div>
    4. </div>
    5. </template>
    6. <script>
    7. // import * as echarts from 'echarts';
    8. // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
    9. import * as echarts from 'echarts/core';
    10. // 引入图表,图表后缀都为 Chart
    11. // import { LineChart } from 'echarts/charts';
    12. // import { BarChart } from 'echarts/charts';
    13. // import { CustomChart } from 'echarts/charts';
    14. import { PieChart } from 'echarts/charts';
    15. // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
    16. import {
    17. // TitleComponent,
    18. TooltipComponent,
    19. GridComponent,
    20. DatasetComponent,
    21. TransformComponent,
    22. // MarkLineComponent,
    23. // MarkAreaComponent,
    24. // MarkPointComponent
    25. } from 'echarts/components';
    26. // 标签自动布局、全局过渡动画等特性
    27. import { LabelLayout, UniversalTransition } from 'echarts/features';
    28. // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
    29. import { CanvasRenderer } from 'echarts/renderers';
    30. // 注册必须的组件
    31. echarts.use([
    32. // TitleComponent,
    33. TooltipComponent,
    34. GridComponent,
    35. DatasetComponent,
    36. TransformComponent,
    37. // MarkLineComponent,
    38. // MarkAreaComponent,
    39. // MarkPointComponent,
    40. // LineChart,
    41. // BarChart,
    42. // CustomChart,
    43. PieChart,
    44. LabelLayout,
    45. UniversalTransition,
    46. CanvasRenderer
    47. ]);
    48. export default {
    49. data() {
    50. return {
    51. status: 'loading',
    52. loading: true,
    53. chart: null
    54. }
    55. },
    56. created() {
    57. },
    58. mounted() {
    59. },
    60. beforeDestroy() {
    61. },
    62. methods: {
    63. draw(sourceData) {
    64. // console.log(sourceData)
    65. // 基于准备好的dom,初始化echarts实例
    66. if (!this.chart) {
    67. this.chart = echarts.init(document.getElementById('mulPieChart'));
    68. }
    69. // 指定图表的配置项和数据
    70. let option = {
    71. tooltip: {
    72. trigger: 'item'
    73. },
    74. series: [
    75. {
    76. type: 'pie',
    77. name: '',
    78. radius: [55, 62],
    79. legendHoverLink: false,
    80. avoidLabelOverlap: false,
    81. selectedOffset: 0,
    82. padAngle: 2,
    83. itemStyle: {
    84. borderRadius: 2
    85. },
    86. label: {
    87. show: true,
    88. position: 'center'
    89. },
    90. emphasis: {
    91. label: {
    92. show: false,
    93. fontSize: 40,
    94. fontWeight: 'bold'
    95. }
    96. },
    97. labelLine: {
    98. show: false
    99. },
    100. data: sourceData,
    101. itemStyle: {
    102. normal: {
    103. color: function (params) {
    104. var colorList = [
    105. ['#469C94', '#6AE6C8'],
    106. ['#21C5F5', '#043748'],
    107. ['#23A9FF', '#0321BD'],
    108. ['#FF7500', '#FF7500'],
    109. ['#a72a21', '#803d37'],
    110. ['#7b0488', '#3c1e69'],
    111. ['#ff00bf', '#651754'],
    112. ];
    113. var index = params.dataIndex;
    114. return new echarts.graphic.LinearGradient(0, 0, 1, 1, [
    115. {
    116. offset: 0,
    117. color: colorList[index][0]
    118. },
    119. {
    120. offset: 1,
    121. color: colorList[index][1]
    122. }
    123. ]);
    124. }
    125. }
    126. }
    127. }
    128. ]
    129. }
    130. this.chart.setOption(option)
    131. }
    132. }
    133. }
    134. </script>
    135. <style lang="scss" scoped>
    136. </style>

     scale-screen.vue

    1. <template>
    2. <div class="screen-wrapper" :class="{'opacity': opacity}" ref="screenWrapper" :style="wrapperStyle">
    3. <slot></slot>
    4. </div>
    5. </template>
    6. <script>
    7. /**
    8. * 防抖函数
    9. * @param {T} fn
    10. * @param {number} delay
    11. * @return
    12. */
    13. function debounce(fn, delay) {
    14. let timer = null;
    15. return function (...args) {
    16. timer = setTimeout(
    17. () => {
    18. typeof fn === "function" && fn.apply(null, args);
    19. clearTimeout(timer);
    20. },
    21. delay > 0 ? delay : 100
    22. );
    23. };
    24. }
    25. export default {
    26. name: "VScaleScreen",
    27. props: {
    28. width: {
    29. type: [String, Number],
    30. default: 1920,
    31. },
    32. height: {
    33. type: [String, Number],
    34. default: 1080,
    35. },
    36. fullScreen: {
    37. type: Boolean,
    38. default: false,
    39. },
    40. autoScale: {
    41. type: [Object, Boolean],
    42. default: true,
    43. },
    44. selfAdaption: {
    45. type: Boolean,
    46. default: true,
    47. },
    48. delay: {
    49. type: Number,
    50. default: 500,
    51. },
    52. boxStyle: {
    53. type: Object,
    54. default: () => ({}),
    55. },
    56. wrapperStyle: {
    57. type: Object,
    58. default: () => ({}),
    59. },
    60. },
    61. data() {
    62. return {
    63. currentWidth: 0,
    64. currentHeight: 0,
    65. originalWidth: 0,
    66. originalHeight: 0,
    67. onResize: null,
    68. observer: null,
    69. opacity: false
    70. };
    71. },
    72. watch: {
    73. selfAdaption(val) {
    74. if (val) {
    75. this.resize();
    76. this.addListener();
    77. } else {
    78. this.clearListener();
    79. this.clearStyle();
    80. }
    81. },
    82. },
    83. computed: {
    84. screenWrapper() {
    85. return this.$refs["screenWrapper"];
    86. },
    87. },
    88. methods: {
    89. initSize() {
    90. return new Promise((resolve, reject) => {
    91. // console.log("初始化样式");
    92. //给父元素设置 overflow:hidden
    93. this.screenWrapper.parentNode.style.overflow = "hidden";
    94. this.screenWrapper.parentNode.scrollLeft = 0;
    95. this.screenWrapper.parentNode.scrollTop = 0;
    96. this.$nextTick(() => {
    97. // region 获取大屏真实尺寸
    98. if (this.width && this.height) {
    99. this.currentWidth = this.width;
    100. this.currentHeight = this.height;
    101. } else {
    102. this.currentWidth = this.screenWrapper.clientWidth;
    103. this.currentHeight = this.screenWrapper.clientHeight;
    104. }
    105. // endregion
    106. // region 获取画布尺寸
    107. if (!this.originalHeight || !this.originalWidth) {
    108. this.originalWidth = window.screen.width;
    109. this.originalHeight = window.screen.height;
    110. }
    111. // endregion
    112. resolve();
    113. });
    114. });
    115. },
    116. updateSize() {
    117. if (this.currentWidth && this.currentHeight) {
    118. this.screenWrapper.style.width = `${this.currentWidth}px`;
    119. this.screenWrapper.style.height = `${this.currentHeight}px`;
    120. } else {
    121. this.screenWrapper.style.width = `${this.originalWidth}px`;
    122. this.screenWrapper.style.height = `${this.originalHeight}px`;
    123. }
    124. },
    125. handleAutoScale(scale) {
    126. if (!this.autoScale) return;
    127. const screenWrapper = this.screenWrapper;
    128. const domWidth = screenWrapper.clientWidth;
    129. const domHeight = screenWrapper.clientHeight;
    130. const currentWidth = document.body.clientWidth - 232;
    131. const currentHeight = document.body.clientHeight - 111;
    132. screenWrapper.style.transform = `scale(${scale},${scale}) `;
    133. let mx = Math.max((currentWidth - domWidth * scale) / 2, 0);
    134. let my = Math.max((currentHeight - domHeight * scale) / 2, 0);
    135. if (typeof this.autoScale === "object") {
    136. // @ts-ignore
    137. !this.autoScale.x && (mx = 0);
    138. // @ts-ignore
    139. !this.autoScale.y && (my = 0);
    140. }
    141. this.screenWrapper.parentNode.style.height = (this.height * scale) + 'px'
    142. setTimeout(() => {
    143. this.opacity = true
    144. }, 500)
    145. },
    146. updateScale() {
    147. const screenWrapper = this.screenWrapper;
    148. // 获取真实视口尺寸
    149. const currentWidth = document.body.clientWidth - 232;
    150. const currentHeight = document.body.clientHeight - 111;
    151. // 获取大屏最终的宽高onResize
    152. const realWidth = this.currentWidth || this.originalWidth;
    153. const realHeight = this.currentHeight || this.originalHeight;
    154. // 计算缩放比例
    155. const widthScale = currentWidth / realWidth;
    156. const heightScale = currentHeight / realHeight;
    157. // console.log({currentWidth, currentHeight,realWidth,realHeight});
    158. // 若要铺满全屏,则按照各自比例缩放
    159. if (this.fullScreen) {
    160. screenWrapper.style.transform = `scale(${widthScale},${heightScale})`;
    161. return false;
    162. }
    163. // 按照宽高最小比例进行缩放
    164. const scale = Math.max(widthScale, heightScale);
    165. this.handleAutoScale(scale);
    166. },
    167. initMutationObserver() {
    168. const screenWrapper = this.screenWrapper;
    169. const observer = (this.observer = new MutationObserver(() => {
    170. this.onResize();
    171. }));
    172. observer.observe(screenWrapper, {
    173. attributes: true,
    174. attributeFilter: ["style"],
    175. attributeOldValue: true,
    176. });
    177. },
    178. clearListener() {
    179. window.removeEventListener("resize", this.onResize);
    180. },
    181. addListener() {
    182. window.addEventListener("resize", this.onResize);
    183. },
    184. clearStyle() {
    185. const screenWrapper = this.screenWrapper;
    186. screenWrapper.parentNode.style.overflow = "auto";
    187. screenWrapper.style = "";
    188. },
    189. async resize() {
    190. if (!this.selfAdaption) {
    191. return;
    192. }
    193. await this.initSize();
    194. this.updateSize();
    195. this.updateScale();
    196. },
    197. },
    198. mounted() {
    199. this.onResize = debounce(() => {
    200. this.resize();
    201. }, this.delay);
    202. this.$nextTick(() => {
    203. if (this.selfAdaption) {
    204. this.resize();
    205. this.addListener();
    206. }
    207. });
    208. },
    209. beforeDestroy() {
    210. this.clearListener();
    211. },
    212. };
    213. </script>
    214. <style scoped>
    215. .screen-box {
    216. overflow: hidden;
    217. background-size: 100% 100%;
    218. background: #000;
    219. width: 100vw;
    220. height: 100vh;
    221. }
    222. .screen-wrapper {
    223. transition-property: all;
    224. transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    225. transition-duration: 500ms;
    226. position: relative;
    227. overflow: hidden;
    228. z-index: 100;
    229. transform-origin: left top;
    230. opacity: 0;
    231. }
    232. .opacity {
    233. opacity: 1;
    234. }
    235. </style>

  • 相关阅读:
    不知道什么的复习题
    【AlphaHoldem】端到端强化学习玩德州扑克
    【HDU No. 1232】 畅通工程
    消息队列与快递柜之间的奇妙关系
    【数据结构】时间复杂度和空间复杂度
    Spring Boot 热部署与日志
    图像处理: ImageKit.NET 3.0.10704 Crack
    dpdk实现dns
    【AI视野·今日NLP 自然语言处理论文速览 四十九期】Fri, 6 Oct 2023
    生成网络论文阅读styleGAN1(一):论文速览
  • 原文地址:https://blog.csdn.net/qq_42080594/article/details/139412321