HybridCharts.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. <!-- 饼图统计 -->
  2. <template>
  3. <div class="box">
  4. <boxTop :title="title"/>
  5. <div class="cakeBox">
  6. <div class="flex">
  7. <div class="chartsDom" id="PieCharts"></div>
  8. <div class="panel">
  9. <div class="panel-item" v-for="item in chartData">
  10. <div class="color" :style="{'background-color':item.color }"></div>
  11. <div class="type">{{ item.name }}</div>
  12. <div class="number">{{ item.value }}单</div>
  13. <!-- <div class="amount">¥{{ item.amount }}</div>-->
  14. </div>
  15. </div>
  16. </div>
  17. </div>
  18. <div id="rankingCharts"></div>
  19. </div>
  20. </template>
  21. <script>
  22. import boxTop from '@/components/boxTop/index.vue'
  23. export default {
  24. data() {
  25. return {
  26. colorList:['#975fe4','#45a5ff','#81c926','#ff8e49','#37cbcb'],
  27. chartData: [
  28. {
  29. value: 30,
  30. name: "平台一",
  31. color: '#975fe4',
  32. amount: 3395,
  33. },
  34. {
  35. value: 40,
  36. name: "平台二",
  37. color: '#45a5ff',
  38. amount: 2323
  39. },
  40. {
  41. value: 50,
  42. name: "平台三",
  43. color: '#81c926',
  44. amount: 3322
  45. },
  46. {
  47. value: 20,
  48. name: "平台四",
  49. amount: 6644,
  50. color: '#ff8e49'
  51. },
  52. {
  53. value: 16,
  54. name: "平台五",
  55. amount: 3211,
  56. color: '#37cbcb'
  57. },
  58. ]
  59. }
  60. },
  61. components: {
  62. boxTop,
  63. },
  64. props: {
  65. id: {
  66. type: String,
  67. default: ``,
  68. },
  69. data: {
  70. type: Array,
  71. default: [],
  72. },
  73. dataSource:{
  74. type: Array,
  75. default: [],
  76. },
  77. tabIndex: {
  78. type: Number,
  79. default: 0,
  80. },
  81. title: {
  82. type: String,
  83. default: ``,
  84. },
  85. titleEn: {
  86. type: String,
  87. default: `Tongren Tobacco Planting Digital Management Platform`,
  88. },
  89. },
  90. async mounted() {
  91. this.getEchart()
  92. this.getEchartAgain()
  93. },
  94. watch: {
  95. data: {
  96. handler() {
  97. this.chartData = this.data.map((item, index) => ({
  98. value: item.value,
  99. name: item.label,
  100. color: this.colorList[index],
  101. amount:item.ratio
  102. }))
  103. this.getEchart()
  104. this.getEchartAgain()
  105. },
  106. deep: true, // 深度监听
  107. immediate: true, // 立即执行
  108. },
  109. },
  110. methods: {
  111. getEchart() {
  112. let myChart = echarts.init(document.getElementById('PieCharts'))
  113. const sum = this.chartData.reduce((per, cur) => per + cur.value, 0);
  114. const gap = (1 * sum) / 100;
  115. const pieData1 = [];
  116. const gapData = {
  117. name: "",
  118. value: gap,
  119. itemStyle: {
  120. color: "transparent",
  121. },
  122. };
  123. const color = this.chartData.map(item => item.color);
  124. for (let i = 0; i < this.chartData.length; i++) {
  125. // 第一圈数据
  126. pieData1.push({
  127. ...this.chartData[i],
  128. });
  129. pieData1.push(gapData);
  130. }
  131. let option = {
  132. color,
  133. title: {
  134. show: true,
  135. text: sum.toLocaleString(),
  136. subtext: "订单总量",
  137. x: "45%",
  138. y: "35%",
  139. itemGap: 6,
  140. textStyle: {
  141. color: "hsla(179, 100%, 65%, 1)",
  142. fontSize: 24,
  143. fontWeight: "400"
  144. },
  145. subtextStyle: {
  146. color: "#fff",
  147. fontSize: 12,
  148. fontWeight: "400"
  149. },
  150. textAlign: "center",
  151. },
  152. series: [
  153. {
  154. name: "",
  155. type: "pie",
  156. roundCap: true,
  157. radius: ["82%", "92%"],
  158. center: ["50%", "50%"],
  159. data: pieData1,
  160. labelLine: {
  161. length: 8,
  162. length2: 16,
  163. lineStyle: {
  164. width: 1,
  165. },
  166. },
  167. label: {
  168. show: false,
  169. },
  170. },
  171. {
  172. type: "pie",
  173. radius: ["78%", "81%"],
  174. center: ["50%", "50%"],
  175. animation: false,
  176. hoverAnimation: false,
  177. data: [
  178. {
  179. value: 100,
  180. },
  181. ],
  182. label: {
  183. show: false,
  184. },
  185. itemStyle: {
  186. normal: {
  187. color: "#3BC5EF",
  188. },
  189. },
  190. },
  191. {
  192. name: "",
  193. type: "pie",
  194. startAngle: 90,
  195. radius: "77%",
  196. animation: false,
  197. hoverAnimation: false,
  198. center: ["50%", "50%"],
  199. itemStyle: {
  200. normal: {
  201. labelLine: {
  202. show: false,
  203. },
  204. color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
  205. {
  206. offset: 1,
  207. color: "rgba(50,171,241, 0)",
  208. },
  209. {
  210. offset: 0.5,
  211. color: "rgba(50,171,241, .4)",
  212. },
  213. {
  214. offset: 0,
  215. color: "rgba(55,70,130, 0)",
  216. },
  217. ]),
  218. shadowBlur: 60,
  219. },
  220. },
  221. data: [
  222. {
  223. value: 100,
  224. },
  225. ],
  226. },
  227. ],
  228. };
  229. myChart.setOption(option)
  230. },
  231. getEchartAgain() {
  232. let myChart = echarts.init(document.getElementById('rankingCharts'))
  233. const dataSource = this.dataSource;
  234. let dataSourcemax = 0
  235. dataSource.forEach((item) => {
  236. if (dataSourcemax < item.value) {
  237. dataSourcemax = item.value
  238. }
  239. })
  240. const salvProMax = dataSource.map(item => dataSourcemax)
  241. const title = '责任单位指标总数'
  242. let option = {
  243. title: [
  244. {
  245. show: false,
  246. text: title,
  247. fontSize: 20,
  248. color: '#fff',
  249. fontWeight: 600,
  250. x: '70%',
  251. y: '3%',
  252. },
  253. ],
  254. grid: {
  255. left: '6%',
  256. right: '6%',
  257. top: '10%',
  258. bottom: '8%',
  259. },
  260. xAxis: {
  261. show: false,
  262. type: 'value',
  263. max: dataSourcemax + 100
  264. },
  265. yAxis: [
  266. {
  267. type: 'category',
  268. inverse: true,
  269. axisLine: {
  270. show: false
  271. },
  272. axisTick: {
  273. show: false
  274. },
  275. axisLabel: {
  276. color: '#fff',
  277. align: 'left',
  278. verticalAlign: 'bottom',
  279. position: 'right',
  280. padding: [0, 0, 5, 15],
  281. fontSize: 12,
  282. },
  283. data: dataSource.map(item => item.label)
  284. }
  285. ],
  286. tooltip: {
  287. trigger: 'item'
  288. },
  289. series: [
  290. {
  291. type: 'bar',
  292. barWidth: 10,
  293. itemStyle: {
  294. padding: [0, 0, 0, 0],
  295. normal: {
  296. color: new echarts.graphic.LinearGradient(0, 0, 1, 0,
  297. [{
  298. offset: 0,
  299. color: 'rgba(77, 255, 251, 0.3)'
  300. },
  301. {
  302. offset: 1,
  303. color: 'rgba(77, 255, 251, 1)'
  304. }
  305. ], false),
  306. }
  307. },
  308. label: {
  309. show: false,
  310. offset: [10, -20],
  311. formatter: '{c}人',
  312. position: 'insideRight', // 在上方显示
  313. // position: 'insideLeft',
  314. // 数值样式,显示的文字大小和颜色
  315. fontSize: '12',
  316. color: '#f00',
  317. fontWeight: 400,
  318. lineHeight: '18'
  319. },
  320. data: dataSource
  321. },
  322. {
  323. z: 1,
  324. name: '背景',
  325. type: 'bar',
  326. barWidth: 8,
  327. barGap: '-100%',
  328. data: salvProMax,
  329. itemStyle: {
  330. color: 'rgba(0, 255, 255, 0.3)',
  331. // borderRadius: [30, 30, 30, 30]
  332. },
  333. tooltip: {show: false},
  334. label: {
  335. show: true, // 开启显示
  336. offset: [10, -20],
  337. formatter: function (fItem) {
  338. let obj = dataSource.find(item => item.label === fItem.name)
  339. return `{unitWid|交易量}{value|${obj.value}}{unit|交易额}{ratio|${obj.ratio}}`
  340. },
  341. position: 'insideRight', // 在上方显示
  342. // 数值样式,显示的文字大小和颜色
  343. fontSize: '14',
  344. fontWeight: 400,
  345. lineHeight: '18',
  346. rich: {
  347. value: {
  348. color: '#00ffff',
  349. fontSize: 16,
  350. padding: [0, 0, -10, 5]
  351. },
  352. ratio: {
  353. color: '#00ffff',
  354. fontSize: 16,
  355. padding: [0, 0, -10, 5],
  356. align: 'right',
  357. },
  358. unitWid: {
  359. fontSize: 12,
  360. color: 'rgba(255, 255, 255, 0.7)',
  361. padding: [0, 0, -10, 40],
  362. // width: 80,
  363. },
  364. unit: {
  365. fontSize: 12,
  366. color: 'rgba(255, 255, 255, 0.7)',
  367. padding: [0, 0, -10, 40]
  368. }
  369. }
  370. },
  371. }
  372. ]
  373. };
  374. myChart.setOption(option)
  375. }
  376. },
  377. }
  378. </script>
  379. <style lang="less" scoped>
  380. .box {
  381. width: 460px;
  382. height: 428px;
  383. background: linear-gradient(rgba(0, 32, 77, 0.8) 0%, rgba(0, 32, 77, 0.5) 100%);
  384. box-shadow: inset 0px 0px 20px 0px rgba(27, 146, 255, 0.3);
  385. }
  386. #rankingCharts {
  387. width: 460px;
  388. height: 210px;
  389. }
  390. .cakeBox {
  391. width: 460px;
  392. height: 160px;
  393. .chartsDom {
  394. margin: 8px 30px;
  395. width: 150px;
  396. height: 150px;
  397. }
  398. }
  399. .flex {
  400. display: flex;
  401. align-items: center;
  402. }
  403. .l-height {
  404. line-height: 100%;
  405. }
  406. .space_around {
  407. justify-content: space-around;
  408. align-items: center;
  409. }
  410. .space_between {
  411. justify-content: space-between;
  412. align-items: center;
  413. }
  414. .number {
  415. text-align: center;
  416. font-size: 16px;
  417. padding: 4px 0;
  418. margin: 3px 0;
  419. }
  420. .text {
  421. font-size: 14px;
  422. color: #888888;
  423. display: flex;
  424. justify-content: center;
  425. align-items: center;
  426. }
  427. .column_reverse {
  428. flex-direction: column-reverse;
  429. }
  430. .panel {
  431. height: 114px;
  432. box-sizing: border-box;
  433. display: flex;
  434. justify-content: space-around;
  435. flex-direction: column;
  436. .panel-item {
  437. display: flex;
  438. align-items: center;
  439. justify-content: space-around;
  440. height: 20px;
  441. width: 195px;
  442. font-size: 12px;
  443. .color {
  444. border-radius: 2px;
  445. width: 10px;
  446. height: 10px;
  447. }
  448. div{
  449. width: 80px;
  450. text-align: center;
  451. }
  452. }
  453. }
  454. .title {
  455. display: flex;
  456. align-items: center;
  457. margin: 10px 30px;
  458. .label {
  459. font-weight: 600;
  460. font-size: 16px;
  461. color: #FFFFFF;
  462. }
  463. .value {
  464. font-weight: bold;
  465. font-size: 24px;
  466. background: linear-gradient(0deg, rgba(27, 146, 255, 1) 0%, rgba(255, 255, 255, 1) 50%);
  467. background-clip: text;
  468. -webkit-background-clip: text;
  469. -webkit-text-fill-color: transparent;
  470. }
  471. }
  472. .title > * {
  473. margin: 0 6px;
  474. }
  475. .AICenter {
  476. display: flex;
  477. align-items: center
  478. }
  479. </style>