line.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <template>
  2. <div ref="dom" class="charts chart-line"></div>
  3. </template>
  4. <script>
  5. import echarts from 'echarts'
  6. import tdTheme from './theme.json'
  7. import {
  8. on,
  9. off
  10. } from '@/libs/tools'
  11. echarts.registerTheme('tdTheme', tdTheme)
  12. export default {
  13. name: 'ChartLine',
  14. props: {
  15. value: Object, // 单列折线图,key为x轴,value为y轴
  16. text: String,
  17. subtext: String,
  18. color: {
  19. type: Array,
  20. default: function () {
  21. return []
  22. }
  23. },
  24. // 当有多列折线图展示时的X轴坐标数据
  25. xAxisData: {
  26. type: Array,
  27. default: function () {
  28. return []
  29. }
  30. },
  31. // 当有多列折线图展示时的y轴坐标数据
  32. seriesData: {
  33. type: Array,
  34. default: function () {
  35. return []
  36. }
  37. },
  38. // y轴坐标单位
  39. yUnit: {
  40. type: String,
  41. default: ''
  42. },
  43. // x轴标签旋转角度
  44. xAxisRotate: {
  45. type: Number,
  46. default: 0
  47. }
  48. },
  49. watch: {
  50. xAxisData: {
  51. handler (nVal, oVal) {
  52. if (nVal) {
  53. // 根据x轴时间长度控制滚动条位置及显示状态 x轴长度大于25时,显示滚动条并且滚动条结束位置在80%
  54. if (nVal.length > 25) {
  55. this.isShowZoom = true
  56. this.xZoomEnd = 80
  57. } else {
  58. this.isShowZoom = false
  59. this.xZoomEnd = 100
  60. }
  61. if (nVal.length > 30) {
  62. this.xZoomEnd = 70
  63. }
  64. if (nVal.length > 35) {
  65. this.xZoomEnd = 60
  66. }
  67. if (nVal.length > 40) {
  68. this.xZoomEnd = 50
  69. }
  70. if (nVal.length > 45) {
  71. this.xZoomEnd = 40
  72. }
  73. if (nVal.length > 50) {
  74. this.xZoomEnd = 30
  75. }
  76. this.pageInit()
  77. }
  78. },
  79. deep: true,
  80. immediate: true // 代表如果在 wacth 里声明了 xAxisData 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行
  81. },
  82. xAxisRotate: {
  83. handler (nVal, oVal) {
  84. if (nVal !== '') {
  85. this.pageInit()
  86. }
  87. },
  88. deep: true,
  89. immediate: true
  90. }
  91. },
  92. data () {
  93. return {
  94. dom: null, // echarts实例对象
  95. isShowZoom: false, // 是否展示滚动条
  96. xZoomEnd: 100, // x轴滚动条结束位置
  97. yMax: 1000 // y轴最大值
  98. }
  99. },
  100. methods: {
  101. resize () {
  102. this.dom.resize()
  103. },
  104. pageInit () {
  105. const that = this
  106. const legend = this.seriesData.map(_ => _.name)
  107. this.$nextTick(() => {
  108. const xAxisData = this.value ? Object.keys(this.value) : this.xAxisData
  109. const seriesData = this.value ? Object.values(this.value) : this.seriesData
  110. const yMax = this.getYMax(this.seriesData) // 计算最大值
  111. const option = {
  112. color: this.color,
  113. title: {
  114. text: this.text,
  115. subtext: this.subtext,
  116. x: 'left'
  117. },
  118. legend: {
  119. data: legend
  120. },
  121. // 鼠标放上去遮罩层提示信息
  122. tooltip: {
  123. trigger: 'axis'
  124. },
  125. dataZoom: [{ // Y轴固定,让内容滚动
  126. type: 'slider',
  127. show: this.isShowZoom, // flase直接隐藏图形
  128. xAxisIndex: [0],
  129. left: '9%', // 滚动条靠左侧的百分比
  130. bottom: -5,
  131. start: 0, // 滚动条的起始位置
  132. end: this.xZoomEnd, // 滚动条的截止位置(按比例分割你的柱状图x轴长度)
  133. zoomLock: true // 锁定区域禁止缩放(鼠标滚动会缩放,所以禁止)
  134. }],
  135. xAxis: {
  136. type: 'category',
  137. boundaryGap: false, // 两边是否留白
  138. data: xAxisData,
  139. axisLabel: {
  140. interval: 0,
  141. rotate: this.xAxisRotate
  142. },
  143. axisTick: {
  144. inside: true,
  145. lignWithLabel: true // 这两行代码可以让刻度正对刻度名
  146. }
  147. },
  148. yAxis: {
  149. type: 'value',
  150. min: 0,
  151. max: yMax,
  152. axisLabel: {
  153. formatter: `{value} ${this.yUnit}`
  154. },
  155. // interval: 2,
  156. position: 'left'
  157. }
  158. }
  159. if (this.value) {
  160. option.series = [{
  161. data: seriesData,
  162. type: 'line',
  163. barWidth: 35,
  164. label: {
  165. normal: {
  166. show: true,
  167. position: 'top'
  168. }
  169. }
  170. }]
  171. } else {
  172. option.series = this.seriesData
  173. }
  174. // 已创建的先销毁
  175. if (this.dom) {
  176. this.dom.dispose()
  177. }
  178. this.dom = echarts.init(this.$refs.dom, 'tdTheme')
  179. this.dom.setOption(option)
  180. // 更新y轴最大值
  181. this.dom.on('legendselectchanged', function (params) {
  182. // console.log(params, that.seriesData, 'legendselectchanged')
  183. const data = that.seriesData.filter(item => params.selected[item.name])
  184. option.yAxis.max = that.getYMax(data)
  185. that.dom.setOption(option)
  186. })
  187. // 重置图标大小
  188. this.dom.resize()
  189. on(window, 'resize', this.resize)
  190. })
  191. },
  192. // 计算y轴最大值
  193. getYMax (data) {
  194. let max = []
  195. data.map(item => {
  196. max = max.concat(item.data)
  197. })
  198. return Math.max.apply(null, max)
  199. }
  200. },
  201. mounted () {
  202. this.pageInit()
  203. },
  204. beforeDestroy () {
  205. off(window, 'resize', this.resize)
  206. }
  207. }
  208. </script>