pie-chart.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <template>
  2. <div class="chart" id="equipment"></div>
  3. </template>
  4. <script>
  5. import util from "@/helper/util.js";
  6. import partten from "@/helper/partten.js";
  7. import * as echarts from "echarts";
  8. export default {
  9. name: "pie-chart",
  10. componentName: "pie-chart",
  11. props: {
  12. width: {
  13. type: String,
  14. default: "100%",
  15. },
  16. height: {
  17. type: String,
  18. default: "13.889vh",
  19. },
  20. // 传入数据
  21. lossPower: {
  22. type: Object,
  23. default: () => {},
  24. },
  25. // 单位
  26. unit: {
  27. type: String,
  28. default: "",
  29. },
  30. //倍率
  31. ratio: {
  32. type: Number,
  33. default: 1,
  34. },
  35. showLegend: {
  36. type: Boolean,
  37. default: false,
  38. },
  39. // 颜色
  40. color: {
  41. type: Array,
  42. default: () => [
  43. "#005bd9",
  44. "#019f2e",
  45. "#db6200",
  46. "#d24645",
  47. "#f00bd8",
  48. "#9fa0a2",
  49. ],
  50. },
  51. },
  52. data() {
  53. return {
  54. id: "",
  55. chart: null,
  56. newlist: null,
  57. chooseItem: {},
  58. seriesData: [],
  59. };
  60. },
  61. watch: {
  62. lossPower() {
  63. this.seriesData = [
  64. {
  65. value: this.lossPower.XNSS ? this.lossPower?.XNSS?.toFixed(2) : 0,
  66. name: "性能损失",
  67. },
  68. {
  69. value: this.lossPower.WHSS ? this.lossPower?.WHSS?.toFixed(2) : 0,
  70. name: "维护损失",
  71. },
  72. {
  73. value: this.lossPower.GZSS ? this.lossPower?.GZSS?.toFixed(2) : 0,
  74. name: "故障损失",
  75. },
  76. {
  77. value: this.lossPower.XDSS ? this.lossPower?.XDSS?.toFixed(2) : 0,
  78. name: "限电损失",
  79. },
  80. {
  81. value: this.lossPower.SLSS ? this.lossPower?.SLSS?.toFixed(2) : 0,
  82. name: "受累损失",
  83. },
  84. ];
  85. },
  86. },
  87. methods: {
  88. resize() {},
  89. initChart() {
  90. const chart = echarts.init(document.getElementById("equipment"));
  91. let max =
  92. Math.max.apply(
  93. Math,
  94. this.seriesData.map(function (o) {
  95. return o.value;
  96. })
  97. ) || 0;
  98. let index = this.seriesData.findIndex((item) => item.value == max);
  99. let total =
  100. this.seriesData.reduce((a, b) => {
  101. return a + b.value * 1;
  102. }, 0) || 0;
  103. let title = this.seriesData.find((item) => item.value == max)?.name || "";
  104. let option = {
  105. color: this.color,
  106. // radar: [
  107. // {
  108. // indicator: [{ text: "" }],
  109. // center: ["47%", "50%"],
  110. // radius: [0, 79],
  111. // startAngle: 60,
  112. // splitNumber: 5,
  113. // shape: "circle",
  114. // name: {
  115. // formatter: "",
  116. // textStyle: {
  117. // color: "#0000FF",
  118. // },
  119. // },
  120. // splitArea: {
  121. // areaStyle: {
  122. // color: "rgba(0, 0, 0, 0)",
  123. // },
  124. // },
  125. // axisLine: {
  126. // lineStyle: {
  127. // color: "rgba(0, 0, 0, 0)",
  128. // },
  129. // },
  130. // splitLine: {
  131. // lineStyle: {
  132. // color: "#0a389c",
  133. // shadowColor: "#0a389c",
  134. // shadowBlur: 10,
  135. // },
  136. // },
  137. // },
  138. // ],
  139. // tooltip: {
  140. // trigger: "item",
  141. // },
  142. // series: [
  143. // {
  144. // name: "",
  145. // type: "pie",
  146. // radius: [0, 80],
  147. // center: ["47%", "50%"],
  148. // roseType: "area",
  149. // label: {
  150. // formatter: "{d}%",
  151. // padding: [-20, -25, 10, 5],
  152. // },
  153. // itemStyle: {
  154. // normal: {
  155. // // 阴影的大小
  156. // shadowBlur: 20,
  157. // // 阴影水平方向上的偏移
  158. // shadowOffsetX: 0,
  159. // // 阴影垂直方向上的偏移
  160. // shadowOffsetY: 0,
  161. // // 阴影颜色
  162. // shadowColor: "rgba(0,70,199, 0.8)",
  163. // },
  164. // borderRadius: 2,
  165. // },
  166. // data: [
  167. // {
  168. // value: this.lossPower.XNSS
  169. // ? this.lossPower?.XNSS?.toFixed(2)
  170. // : 0,
  171. // name: "性能损失",
  172. // },
  173. // {
  174. // value: this.lossPower.WHSS
  175. // ? this.lossPower?.WHSS?.toFixed(2)
  176. // : 0,
  177. // name: "维护损失",
  178. // },
  179. // {
  180. // value: this.lossPower.GZSS
  181. // ? this.lossPower?.GZSS?.toFixed(2)
  182. // : 0,
  183. // name: "故障损失",
  184. // },
  185. // {
  186. // value: this.lossPower.XDSS
  187. // ? this.lossPower?.XDSS?.toFixed(2)
  188. // : 0,
  189. // name: "限电损失",
  190. // },
  191. // {
  192. // value: this.lossPower.SLSS
  193. // ? this.lossPower?.SLSS?.toFixed(2)
  194. // : 0,
  195. // name: "受累损失",
  196. // },
  197. // ],
  198. // },
  199. // ],
  200. legend: {
  201. top: 40,
  202. right: 30,
  203. orient: "vertical", //改变排列方式
  204. itemGap: 15, // 设置legend的间距
  205. itemWidth: 10, // 设置宽度
  206. itemHeight: 10, // 设置高度
  207. textStyle: {
  208. fontSize: 15,
  209. color: "#fff",
  210. },
  211. itemStyle: {
  212. borderColor: "transparent",
  213. },
  214. },
  215. title: {
  216. text: `{val|${
  217. max && total ? Number((max / total) * 100).toFixed(2) : 0
  218. }%}\n{name|${title || ""}}`,
  219. top: "43%",
  220. left: "34%",
  221. textAlign: "center",
  222. textStyle: {
  223. rich: {
  224. name: {
  225. fontSize: 15,
  226. fontWeight: "bold",
  227. color: this.color[index],
  228. },
  229. val: {
  230. fontSize: 14,
  231. fontWeight: "bold",
  232. color: this.color[index],
  233. },
  234. },
  235. },
  236. },
  237. series: [
  238. {
  239. radius: ["60%", "65%"],
  240. center: ["35%", "50%"],
  241. type: "pie",
  242. avoidLabelOverlap: false,
  243. hoverAnimation: false,
  244. label: {
  245. position: "center",
  246. normal: {
  247. fontSize: 14,
  248. fontWeight: "bold",
  249. show: true,
  250. padding: [-25, -40, 5, 1],
  251. formatter: (params) => {
  252. return `${params.name}${params.percent}%`;
  253. },
  254. },
  255. },
  256. labelLine: {
  257. lineStyle: {
  258. width: 1,
  259. },
  260. },
  261. itemStyle: {
  262. borderColor: "#000",
  263. },
  264. data: this.seriesData,
  265. },
  266. {
  267. name: "",
  268. type: "pie",
  269. radius: ["30%", "60%"],
  270. center: ["35%", "50%"],
  271. avoidLabelOverlap: false,
  272. hoverAnimation: false,
  273. itemStyle: {
  274. opacity: 0.8,
  275. color: "#35383f",
  276. borderColor: "#000",
  277. },
  278. label: {
  279. show: false,
  280. },
  281. labelLine: {
  282. show: false,
  283. },
  284. data: this.seriesData,
  285. },
  286. ],
  287. };
  288. chart.clear();
  289. chart.setOption(option);
  290. chart.on("mouseover", (event) => {
  291. let name = event.name;
  292. let value = event.percent;
  293. option.title.text = "{val|" + value + "%}\n{name|" + name + "}";
  294. option.animation = false;
  295. option.title.textStyle = {
  296. rich: {
  297. name: {
  298. fontSize: 15,
  299. fontWeight: "bold",
  300. color: this.color[event.dataIndex],
  301. },
  302. val: {
  303. fontSize: 14,
  304. fontWeight: "bold",
  305. color: this.color[event.dataIndex],
  306. },
  307. },
  308. };
  309. chart.setOption(option);
  310. });
  311. chart.on("mouseout", (event) => {
  312. option.animation = false;
  313. option.title = {
  314. text: `{val|${
  315. max && total ? Number((max / total) * 100).toFixed(2) : 0
  316. }%}\n{name|${title || ""}}`,
  317. top: "43%",
  318. left: "34%",
  319. textAlign: "center",
  320. textStyle: {
  321. rich: {
  322. name: {
  323. fontSize: 15,
  324. fontWeight: "bold",
  325. color: this.color[index],
  326. // padding: [10, 10],
  327. },
  328. val: {
  329. fontSize: 14,
  330. fontWeight: "bold",
  331. color: this.color[index],
  332. },
  333. },
  334. },
  335. };
  336. chart.setOption(option);
  337. });
  338. this.resize = function () {
  339. chart.resize();
  340. };
  341. window.addEventListener("resize", this.resize);
  342. },
  343. },
  344. created() {
  345. this.$nextTick(() => {});
  346. },
  347. mounted() {
  348. this.$nextTick(() => {
  349. let el = this.$el.parentElement;
  350. el.style.width = this.width;
  351. el.style.height = this.height;
  352. this.initChart();
  353. });
  354. },
  355. updated() {
  356. this.$nextTick(() => {
  357. this.initChart();
  358. });
  359. },
  360. unmounted() {
  361. window.removeEventListener("resize", this.resize);
  362. },
  363. };
  364. </script>
  365. <style lang="less">
  366. .chart {
  367. width: 100%;
  368. height: 100%;
  369. display: inline-block;
  370. }
  371. </style>