1
0

BarSingle2.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <template>
  2. <div ref="chartRef" :style="{ height, width }"></div>
  3. </template>
  4. <script lang="ts">
  5. import { defineComponent, PropType, ref, Ref, reactive, watchEffect, onMounted } from 'vue';
  6. import { useECharts } from '/@/hooks/web/useECharts';
  7. import { toEchartsData } from '/@/utils/ventutil';
  8. import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  9. import EchartsUtil from '/@/utils/echartsUtil';
  10. export default defineComponent({
  11. name: 'BarAndLine',
  12. props: {
  13. chartsColumns: {
  14. type: Array,
  15. default: () => [],
  16. },
  17. chartsColumnsType: {
  18. type: String,
  19. },
  20. dataSource: {
  21. type: Object,
  22. default: () => { },
  23. },
  24. xAxisData: {
  25. type: Array,
  26. default: () => [],
  27. },
  28. width: {
  29. type: String as PropType<string>,
  30. default: '100%',
  31. },
  32. height: {
  33. type: String as PropType<string>,
  34. default: 'calc(100vh - 78px)',
  35. },
  36. },
  37. setup(props) {
  38. const chartRef = ref<HTMLDivElement | null>(null);
  39. const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>);
  40. const chartData = getTableHeaderColumns(props.chartsColumnsType) || [];
  41. const chartsColumns: [] = props.chartsColumns.length > 0 ? props.chartsColumns : chartData;
  42. const labels = ['春节', '元宵节', '端午节', '中秋节'];
  43. const seriesData = [
  44. {
  45. label: '春节',
  46. value: [32],
  47. },
  48. {
  49. label: '元宵节',
  50. value: [24],
  51. },
  52. {
  53. label: '端午节',
  54. value: [42],
  55. },
  56. {
  57. label: '中秋节',
  58. value: [20],
  59. }
  60. ]
  61. const colors = [
  62. [
  63. // { offset: 0, color: 'rgba(73, 190, 255, 1)' },
  64. { offset: 0.5, color: 'rgba(14, 159, 255, 1)' },
  65. { offset: 0.6, color: 'rgba(97, 199, 252, 0.8)' },
  66. { offset: 1, color: 'rgba(97, 199, 252, 0.08)' },
  67. ],
  68. [
  69. { offset: 0.5, color: 'rgba(137, 163, 164, 1)' },
  70. { offset: 1, color: 'rgba(137, 163, 164, 0.8)' },
  71. { offset: 1, color: 'rgba(137, 163, 164, 0.08)' },
  72. ],
  73. [
  74. { offset: 0.5, color: 'rgba(44, 166, 166, 1)' },
  75. { offset: 1, color: 'rgba(44, 166, 166, 0.8)' },
  76. { offset: 1, color: 'rgba(44, 166, 166, 0.08)' },
  77. ],
  78. [
  79. { offset: 0.5, color: 'rgba(34, 66, 186, 1)' },
  80. { offset: 1, color: 'rgba(34, 66, 186, 0.8)' },
  81. { offset: 1, color: 'rgba(34, 66, 186, 0.08)' },
  82. ],
  83. ];
  84. const option = reactive({
  85. xAxis: {
  86. axisLine: {
  87. show: true,
  88. lineStyle: {
  89. color: '#006c9d',
  90. },
  91. },
  92. axisTick: {
  93. show: false
  94. },
  95. nameTextStyle: {
  96. color: '#fff'
  97. },
  98. splitLine: {
  99. lineStyle: {
  100. color: 'rgba(21,80,126,.3)',
  101. type: 'dashed', //设置网格线类型 dotted:虚线 solid:实线
  102. },
  103. show: true,
  104. },
  105. showBackground: true,
  106. backgroundStyle: {
  107. color: 'rgba(205, 95, 255, 1)',
  108. },
  109. data: [],
  110. },
  111. legend: {
  112. // data: getlegendData(),
  113. data: [],
  114. right: '0',
  115. top: '18',
  116. icon: 'rect',
  117. itemHeight: 10,
  118. itemWidth: 10,
  119. textStyle: {
  120. color: '#fff'
  121. }
  122. },
  123. yAxis: {
  124. type: 'value',
  125. alignTicks: true,
  126. axisLine: {
  127. show: true,
  128. lineStyle: {
  129. color: '#006c9d',
  130. },
  131. },
  132. axisLabel: {
  133. show: true,
  134. color: '#ffffffcc',
  135. // formatter: '{value}' + item.yname
  136. },
  137. splitLine: {
  138. lineStyle: {
  139. color: 'rgba(21,80,126,.3)',
  140. type: 'dashed', //设置网格线类型 dotted:虚线 solid:实线
  141. },
  142. // show: item.linetype == 'line' ? true : false,
  143. show: true,
  144. },
  145. showBackground: true,
  146. backgroundStyle: {
  147. color: 'rgba(205, 95, 255, 1)',
  148. },
  149. },
  150. // series: getSeriesData()
  151. series: []
  152. });
  153. // 定义柱状图左侧图形元素
  154. const CubeLeft = echarts.graphic.extendShape({
  155. buildPath: function (ctx, shape) {
  156. const { topBasicsYAxis, bottomYAxis, basicsXAxis } = shape;
  157. // 侧面宽度
  158. const WIDTH = 15;
  159. // 斜角高度
  160. const OBLIQUE_ANGLE_HEIGHT = 4;
  161. const p1 = [basicsXAxis - WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
  162. const p2 = [basicsXAxis - WIDTH, bottomYAxis];
  163. const p3 = [basicsXAxis, bottomYAxis];
  164. const p4 = [basicsXAxis, topBasicsYAxis];
  165. ctx.moveTo(p1[0], p1[1]);
  166. ctx.lineTo(p2[0], p2[1]);
  167. ctx.lineTo(p3[0], p3[1]);
  168. ctx.lineTo(p4[0], p4[1]);
  169. },
  170. });
  171. // 定义柱状图右侧以及顶部图形元素
  172. const CubeRight = echarts.graphic.extendShape({
  173. buildPath: function (ctx, shape) {
  174. const { topBasicsYAxis, bottomYAxis, basicsXAxis } = shape;
  175. // 侧面宽度
  176. const WIDTH = 15;
  177. // 斜角高度
  178. const OBLIQUE_ANGLE_HEIGHT = 4;
  179. const p1 = [basicsXAxis, topBasicsYAxis];
  180. const p2 = [basicsXAxis, bottomYAxis];
  181. const p3 = [basicsXAxis + WIDTH, bottomYAxis];
  182. const p4 = [basicsXAxis + WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
  183. ctx.moveTo(p1[0], p1[1]);
  184. ctx.lineTo(p2[0], p2[1]);
  185. ctx.lineTo(p3[0], p3[1]);
  186. ctx.lineTo(p4[0], p4[1]);
  187. }
  188. });
  189. // 绘制顶面
  190. const CubeTop = echarts.graphic.extendShape({
  191. buildPath: function (ctx, shape) {
  192. const { topBasicsYAxis, basicsXAxis } = shape;
  193. // 侧面宽度
  194. const WIDTH = 15;
  195. // 斜角高度
  196. const OBLIQUE_ANGLE_HEIGHT = 4;
  197. const p1 = [basicsXAxis, topBasicsYAxis];
  198. const p2 = [basicsXAxis + WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
  199. const p3 = [basicsXAxis, topBasicsYAxis - (OBLIQUE_ANGLE_HEIGHT * 2)];
  200. const p4 = [basicsXAxis - WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
  201. ctx.moveTo(p1[0], p1[1]);
  202. ctx.lineTo(p2[0], p2[1]);
  203. ctx.lineTo(p3[0], p3[1]);
  204. ctx.lineTo(p4[0], p4[1]);
  205. },
  206. });
  207. // 注册图形元素
  208. echarts.graphic.registerShape('CubeLeft', CubeLeft);
  209. echarts.graphic.registerShape('CubeRight', CubeRight);
  210. echarts.graphic.registerShape('CubeTop', CubeTop);
  211. function getlegendData() {
  212. const data = <any[]>[];
  213. labels.forEach((item, index) => {
  214. data.push(
  215. {
  216. name: item,
  217. itemStyle: {
  218. color: new echarts.graphic.LinearGradient(1, 0, 0, 0, colors[index]),
  219. },
  220. }
  221. )
  222. })
  223. return data
  224. }
  225. function getSeriesData() {
  226. const data = <any[]>[];
  227. seriesData.forEach((item, index) => {
  228. data.push(
  229. {
  230. type: 'custom',
  231. name: item.label,
  232. renderItem: function (params, api) {
  233. return getRenderItem(params, api);
  234. },
  235. data: item.value,
  236. itemStyle: {
  237. color: () => {
  238. return new echarts.graphic.LinearGradient(0, 0, 0, 1, colors[index]);
  239. },
  240. },
  241. }
  242. )
  243. })
  244. return data
  245. }
  246. function getRenderItem(params, api) {
  247. const index = params.seriesIndex;
  248. let location = api.coord([api.value(0), api.value(1)]);
  249. // 顶部基础 y 轴
  250. const topBasicsYAxis = location[1];
  251. // 基础 x 轴
  252. const basicsXAxis = location[0];
  253. // 底部 y 轴
  254. const bottomYAxis = api.coord([api.value(0), 0])[1];
  255. var extent = api.size([0, api.value(1)]);
  256. // const location = api.coord([api.value(0), api.value(1)]);
  257. let cubeLeftStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, colors[index]);
  258. let cubeRightStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, colors[index]);
  259. let cubeTopStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, colors[index]);
  260. return {
  261. type: 'group',
  262. children: [
  263. {
  264. type: 'CubeLeft',
  265. shape: {
  266. topBasicsYAxis,
  267. basicsXAxis,
  268. bottomYAxis,
  269. },
  270. style: {
  271. ...api.style(),
  272. stroke: '#ffffff33',
  273. fill: cubeLeftStyle,
  274. }
  275. },
  276. {
  277. type: 'CubeRight',
  278. shape: {
  279. topBasicsYAxis,
  280. basicsXAxis,
  281. bottomYAxis,
  282. },
  283. style: {
  284. ...api.style(),
  285. stroke: '#ffffff33',
  286. fill: cubeRightStyle,
  287. }
  288. },
  289. {
  290. type: 'CubeTop',
  291. shape: {
  292. topBasicsYAxis,
  293. basicsXAxis,
  294. bottomYAxis,
  295. },
  296. style: {
  297. ...api.style(),
  298. stroke: '#ffffff33',
  299. fill: cubeTopStyle,
  300. }
  301. }
  302. ]
  303. };
  304. }
  305. watchEffect(() => {
  306. props.dataSource && option.series && initCharts();
  307. });
  308. // function initChartsOption() {
  309. // const optionUtil = new EchartsUtil(option);
  310. // optionUtil.initChartOption('listMonitor', chartsColumns);
  311. // console.log('option----------->', option);
  312. // }
  313. // initChartsOption();
  314. function initCharts() {
  315. //轴数据
  316. if (option.series) {
  317. const xAxisData: any[] = [];
  318. const series: any[] = [];
  319. const seriesData: any[] = [];
  320. const legendData: { name: string, itemStyle: Object }[] = [];
  321. props.xAxisData.forEach((item: any, index) => {
  322. xAxisData.push(item['key']);
  323. seriesData.push(props.dataSource[item.valueKey] || '');
  324. });
  325. for (let i = 0; i < chartsColumns.length; i++) {
  326. const item: any = chartsColumns[i]
  327. legendData.push({
  328. name: item.legend + (item.yname ? '(' + item.yname + ')' : ''),
  329. itemStyle: {
  330. color: new echarts.graphic.LinearGradient(1, 0, 0, 0, colors[i]),
  331. },
  332. })
  333. series.push(
  334. {
  335. type: 'custom',
  336. name: item.legend + (item.yname ? '(' + item.yname + ')' : ''),
  337. renderItem: function (params, api) {
  338. return getRenderItem(params, api);
  339. },
  340. data: seriesData,
  341. })
  342. }
  343. option.legend.data = legendData
  344. // option.series[0].data = seriesData;
  345. option.series = series;
  346. option.xAxis.data = xAxisData;
  347. console.log('option------------->', option);
  348. setOptions(option, false);
  349. }
  350. }
  351. return { chartRef };
  352. },
  353. });
  354. </script>