proportion.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <template>
  2. <!-- 企业钢瓶占比 -->
  3. <div class="border" :style="{height: boxHeight}">
  4. <div class="card_box">
  5. <div class="title_trapezoid center_in">
  6. <span class="center_in">{{title}}</span>
  7. </div>
  8. </div>
  9. <div class="card_collect">
  10. <div id="proportion"></div>
  11. </div>
  12. </div>
  13. </template>
  14. <script>
  15. export default {
  16. name: 'wavyBlock',
  17. props: {
  18. title: {
  19. type: String,
  20. default: () => '文字',
  21. },
  22. boxHeight: {
  23. type: String,
  24. default: () => '95%',
  25. },
  26. dataList: {
  27. type: Array,
  28. default: () => [],
  29. },
  30. },
  31. data() {
  32. return {
  33. proportionList: [],
  34. }
  35. },
  36. watch: {
  37. dataList: {
  38. deep: true, // 立即触发监听函数
  39. immediate: true,
  40. handler(newVal) {
  41. if (newVal) {
  42. this.proportionList = newVal;
  43. }
  44. this.$nextTick(() => {
  45. this.getEnterpriseCylinder()
  46. })
  47. },
  48. },
  49. },
  50. mounted() {},
  51. methods: {
  52. getEnterpriseCylinder() {
  53. var chartDom = document.getElementById('proportion');
  54. var myChart = this.$echarts.init(chartDom);
  55. const nameList = [];
  56. const valueList = [];
  57. if (this.proportionList.length > 0) {
  58. this.proportionList.forEach((item, index) => {
  59. nameList.push(item.name)
  60. valueList.push(item.count)
  61. })
  62. }
  63. let showFlag = true
  64. if (this.proportionList.length > 0) {
  65. showFlag = false
  66. } else if (this.proportionList.length == 0) {
  67. showFlag = true
  68. }
  69. const sum = valueList.reduce((per, cur) => per + cur, 0); // 总数
  70. const showNum = 5;
  71. const option = {
  72. title: {
  73. show: showFlag,
  74. textStyle: {
  75. color: '#ffffff',
  76. fontSize: 18,
  77. fontWeight: 'normal',
  78. },
  79. text: '暂无数据',
  80. left: 'center',
  81. top: 'center',
  82. },
  83. // backgroundColor: "#1e1e1e",
  84. dataZoom: [{
  85. id: 'dataZoom',
  86. show: true, //flase直接隐藏图形
  87. type: 'slider',
  88. backgroundColor: 'transparent',
  89. brushSelect: false,
  90. filterMode: 'none',
  91. width: 7,
  92. yAxisIndex: [0, 1, 2],
  93. //left: 'center', //滚动条靠左侧的百分比
  94. //bottom: 13,
  95. startValue: 0, //滚动条的起始位置
  96. endValue: showNum - 1, //滚动条的截止位置(按比例分割你的柱状图x轴长度)
  97. handleStyle: {
  98. color: 'rgba(0,178,255,0.8)',
  99. borderColor: 'rgba(0,178,255,0.8)'
  100. },
  101. fillerColor: 'rgba(0,178,255,0.8)',
  102. borderColor: 'transparent',
  103. showDetail: false,
  104. dataBackground: {
  105. areaStyle: {
  106. opacity: 0
  107. },
  108. lineStyle: {
  109. color: 'transparent'
  110. }
  111. }
  112. },
  113. {
  114. type: 'inside',
  115. yAxisIndex: [0, 1, 2],
  116. zoomOnMouseWheel: false, //滚轮是否触发缩放
  117. moveOnMouseMove: true, //鼠标滚轮触发滚动
  118. moveOnMouseWheel: true
  119. }
  120. ],
  121. grid: {
  122. left: '48',
  123. right: '24',
  124. bottom: '14',
  125. top: '14'
  126. },
  127. tooltip: {
  128. show: false
  129. },
  130. xAxis: {
  131. show: false,
  132. type: 'value',
  133. boundaryGap: ['0%', '1%']
  134. //max: 100
  135. },
  136. yAxis: [{
  137. id: 'yAxis1',
  138. type: 'category',
  139. inverse: true,
  140. axisLabel: {
  141. inside: true,
  142. align: 'left',
  143. verticalAlign: 'bottom',
  144. padding: [0, 0, 15, -7],
  145. textStyle: {
  146. color: '#ffffff',
  147. fontSize: '14',
  148. fontFamily: 'Source Han Sans CN-Regular',
  149. fontWeight: 400
  150. },
  151. overflow: 'truncate', // 截断超出的部分
  152. formatter: function(value) {
  153. if (value.length > 8) { // 当标签长度超过5时
  154. return value.substring(0, 8) + '...'; // 截断并添加省略号
  155. } else {
  156. return value;
  157. }
  158. }
  159. },
  160. splitLine: {
  161. show: false
  162. },
  163. axisTick: {
  164. show: false
  165. },
  166. axisLine: {
  167. show: false
  168. },
  169. data: nameList
  170. },
  171. {
  172. id: 'yAxis2',
  173. type: 'category',
  174. inverse: true,
  175. axisTick: 'none',
  176. axisLine: 'none',
  177. show: true,
  178. axisLabel: {
  179. padding: [0, 10, 15, 0],
  180. verticalAlign: 'bottom',
  181. align: 'right',
  182. formatter: (value) => {
  183. return `{value|${value}}{unit|瓶}`;
  184. },
  185. rich: {
  186. value: {
  187. color: 'rgba(255,255,255, 1)',
  188. fontFamily: 'HarmonyOS Sans-Regular',
  189. fontSize: '16'
  190. },
  191. unit: {
  192. color: 'rgba(255,255,255, 1)',
  193. fontFamily: 'Source Han Sans CN-Regular',
  194. fontSize: '14'
  195. }
  196. }
  197. },
  198. data: valueList
  199. },
  200. {
  201. id: 'yAxis3',
  202. splitLine: {
  203. show: false
  204. },
  205. axisLine: {
  206. //y轴
  207. show: false
  208. },
  209. type: 'category',
  210. axisTick: {
  211. show: false
  212. },
  213. inverse: true, // 倒序
  214. data: nameList,
  215. position: 'left',
  216. axisLabel: {
  217. color: 'rgba(0, 0, 0, 0.65)',
  218. padding: [0, 0, -3, -32],
  219. align: 'left',
  220. verticalAlign: 'bottom',
  221. formatter: (value, index) => {
  222. let i = nameList.indexOf(value);
  223. if (i == 0) {
  224. return `{lg1|${i + 1}}`;
  225. } else if (i == 1) {
  226. return `{lg2|${i + 1}}`;
  227. } else if (i == 2) {
  228. return `{lg3|${i + 1}}`;
  229. } else {
  230. return `{lg|${i + 1}}`;
  231. }
  232. },
  233. rich: {
  234. lg1: {
  235. backgroundColor: 'rgba(250, 84, 28, 0.20)',
  236. color: 'rgba(255, 122, 69, 1)',
  237. borderRadius: 6,
  238. align: 'center',
  239. width: 28,
  240. height: 28,
  241. lineHeight: 28,
  242. verticalAlign: 'middle',
  243. fontSize: 14,
  244. fontFamily: 'HarmonyOS Sans-Regular'
  245. },
  246. lg2: {
  247. backgroundColor: 'rgba(250, 173, 20, 0.20)',
  248. color: 'rgba(250, 173, 20, 1)',
  249. borderRadius: 6,
  250. align: 'center',
  251. width: 28,
  252. height: 28,
  253. lineHeight: 28,
  254. verticalAlign: 'middle',
  255. fontSize: 14,
  256. fontFamily: 'HarmonyOS Sans-Regular'
  257. },
  258. lg3: {
  259. backgroundColor: 'rgba(35, 214, 136, 0.20)',
  260. color: 'rgba(35, 214, 136, 1)',
  261. borderRadius: 6,
  262. align: 'center',
  263. width: 28,
  264. height: 28,
  265. lineHeight: 28,
  266. verticalAlign: 'middle',
  267. fontSize: 14,
  268. fontFamily: 'HarmonyOS Sans-Regular'
  269. },
  270. lg: {
  271. backgroundColor: 'rgba(57, 126, 240, 0.20)',
  272. color: '#397EF0',
  273. borderRadius: 6,
  274. align: 'center',
  275. width: 28,
  276. height: 28,
  277. lineHeight: 28,
  278. verticalAlign: 'middle',
  279. fontSize: 14,
  280. fontFamily: 'HarmonyOS Sans-Regular'
  281. }
  282. }
  283. }
  284. }
  285. ],
  286. series: [{
  287. name: '值',
  288. type: 'bar',
  289. id: 'bar1',
  290. barCategoryGap: '50%', // 柱子距离
  291. showBackground: true,
  292. barGap: '-140%',
  293. backgroundStyle: {
  294. color: 'rgba(26, 71, 172, 0.3)'
  295. },
  296. itemStyle: {
  297. color: {
  298. type: 'linear',
  299. x: 0,
  300. y: 0,
  301. x2: 1,
  302. y2: 0,
  303. colorStops: [{
  304. offset: 0,
  305. color: 'rgba(39, 92, 226, 0.6)'
  306. },
  307. {
  308. offset: 1,
  309. color: 'rgba(40, 252, 255, 1)'
  310. }
  311. ],
  312. global: false // 缺省为 false
  313. }
  314. },
  315. barWidth: 5,
  316. data: valueList
  317. },
  318. {
  319. name: 'max',
  320. type: 'bar',
  321. id: 'bar2',
  322. data: valueList,
  323. barWidth: 9,
  324. stack: 'max',
  325. itemStyle: {
  326. color: 'transparent'
  327. }
  328. },
  329. {
  330. name: 'max',
  331. type: 'bar',
  332. id: 'bar3',
  333. data: valueList.map((item) => sum / 1000),
  334. barWidth: 9,
  335. stack: 'max',
  336. itemStyle: {
  337. color: '#80D0FB'
  338. }
  339. },
  340. ]
  341. };
  342. let currentIndex = 0;
  343. setInterval(() => {
  344. if (currentIndex + showNum < nameList.length) {
  345. currentIndex = currentIndex + 1;
  346. } else {
  347. currentIndex = 0;
  348. }
  349. myChart.setOption({
  350. dataZoom: [{
  351. id: 'dataZoom',
  352. startValue: currentIndex,
  353. endValue: currentIndex + showNum - 1
  354. }]
  355. });
  356. }, 3000);
  357. option && myChart.setOption(option);
  358. }
  359. }
  360. }
  361. </script>
  362. <style lang="scss">
  363. .border {
  364. position: relative;
  365. width: calc(100% - 10px);
  366. border: 1px solid #3077ca;
  367. margin: 0 10px 0 auto;
  368. border-radius: 4px;
  369. box-shadow: inset 0 0 40px rgba(48, 119, 202, 0.3);
  370. }
  371. .card_box {
  372. position: absolute;
  373. top: 0;
  374. left: calc(50% - 80px);
  375. right: 0;
  376. }
  377. .title_trapezoid {
  378. position: relative;
  379. color: #fff !important;
  380. width: 160px;
  381. height: 30px;
  382. text-align: center;
  383. z-index: 2;
  384. }
  385. .title_trapezoid span {
  386. position: absolute;
  387. left: 0;
  388. bottom: 0;
  389. width: 160px;
  390. top: -1px;
  391. z-index: 2;
  392. font-size: 15px;
  393. line-height: 25px;
  394. }
  395. .title_trapezoid::before {
  396. border-bottom: 2px solid #2CD5FF;
  397. content: '';
  398. z-index: 1;
  399. width: 100%;
  400. height: 30px;
  401. background-image: linear-gradient(to top, #3077ca99, #3077ca7f, transparent);
  402. display: inline-block;
  403. position: absolute;
  404. left: 0;
  405. top: -1px;
  406. transform: perspective(100px) rotateX(150deg);
  407. }
  408. .card_collect {
  409. display: flex;
  410. flex-wrap: wrap;
  411. flex-direction: row;
  412. margin-top: 30px;
  413. height: calc(100% - 30px);
  414. }
  415. #proportion {
  416. width: 100%;
  417. height: 100%;
  418. }
  419. </style>