barChart.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <script setup>
  2. import util from "@tools/util";
  3. import chartTheme from "./barChart.json";
  4. import { ref, toRaw, computed, onMounted, watch, nextTick } from "vue";
  5. import * as echarts from "echarts";
  6. const chartId = "chart-" + util.newGUID(); //chartId
  7. const chartIns = ref(null); //chart 实例
  8. const emits = defineEmits(["getSelected"]);
  9. const props = defineProps({
  10. xAxis: {
  11. type: Object,
  12. required: true,
  13. default: () => ({}),
  14. },
  15. yAxis: {
  16. type: Array,
  17. required: false,
  18. },
  19. colors: {
  20. type: Array,
  21. default: () => [],
  22. },
  23. series: {
  24. type: Array,
  25. required: true,
  26. },
  27. dataset: {
  28. type: Array,
  29. required: false,
  30. default: () => [],
  31. },
  32. height: {
  33. type: String,
  34. required: false,
  35. default: "500px",
  36. },
  37. width: {
  38. type: String,
  39. required: false,
  40. default: "500px",
  41. },
  42. title: {
  43. type: String,
  44. required: false,
  45. },
  46. subtext: {
  47. type: String,
  48. required: false,
  49. },
  50. brush: {
  51. type: Boolean,
  52. required: false,
  53. default: false,
  54. },
  55. theme: {
  56. type: Boolean,
  57. default: false,
  58. },
  59. echartsTheme: {
  60. type: String,
  61. default: "",
  62. },
  63. });
  64. /**定义option */
  65. const option = computed({
  66. get() {
  67. const theme = sessionStorage.getItem("theme") === "true" ? true : false;
  68. return {
  69. backgroundColor: "",
  70. color: props.colors.length
  71. ? props.colors
  72. : [
  73. "rgb(50,93,171)",
  74. "rgb(222,132,82)",
  75. "rgb(105,188,80)",
  76. "rgb(197,78,82)",
  77. "rgb(129,114,181)",
  78. "#005eaa",
  79. "#cda819",
  80. "#32a487",
  81. ],
  82. title: {
  83. text: props.title || "",
  84. subtext: props.subtext || "",
  85. top: 6,
  86. left: "5%",
  87. },
  88. xAxis: props.xAxis || {},
  89. yAxis: props.yAxis || {},
  90. brush: {
  91. seriesIndex: [1],
  92. yAxisIndex: 0,
  93. transformable: true,
  94. throttleType: "debounce",
  95. throttleDelay: 1000,
  96. removeOnClick: true,
  97. brushType: props.brush ? "polygon" : false,
  98. brushMode: "multiple",
  99. brushStyle: {
  100. borderWidth: 1,
  101. borderColor: "#ff2424",
  102. },
  103. },
  104. toolbox: {
  105. show: props.brush,
  106. },
  107. tooltip: {
  108. confine: true,
  109. trigger: "axis",
  110. },
  111. dataset: props.dataset || [],
  112. series: props.series || [],
  113. legend: {
  114. right: "120",
  115. top: "5",
  116. itemWidth: 6,
  117. textStyle: {
  118. color: theme ? "#000" : "#fff",
  119. fontSize: 12,
  120. },
  121. },
  122. grid: {
  123. top: 80,
  124. left: 40,
  125. right: 40,
  126. bottom: 40,
  127. },
  128. dataZoom: [
  129. {
  130. type: "inside", //图表下方的伸缩条
  131. show: false, //是否显示
  132. realtime: true, //拖动时,是否实时更新系列的视图
  133. start: 0, //伸缩条开始位置(1-100),可以随时更改
  134. end: 100, //伸缩条结束位置(1-100),可以随时更改
  135. },
  136. {
  137. type: "slider", //图表下方的伸缩条
  138. show: false, //是否显示
  139. realtime: true, //拖动时,是否实时更新系列的视图
  140. start: 0, //伸缩条开始位置(1-100),可以随时更改
  141. end: 100, //伸缩条结束位置(1-100),可以随时更改
  142. },
  143. ],
  144. };
  145. },
  146. set(val) {},
  147. });
  148. watch(
  149. () => option,
  150. (newVal, oldVal) => {
  151. if (chartIns.value) {
  152. const echartIns = toRaw(chartIns.value);
  153. echartIns.setOption(toRaw(newVal.value));
  154. }
  155. },
  156. {
  157. deep: true,
  158. }
  159. );
  160. watch([() => props.width, () => props.height], (newVal, oldVal) => {
  161. if (chartIns.value) {
  162. const echartIns = toRaw(chartIns.value);
  163. nextTick(() => echartIns.resize());
  164. }
  165. });
  166. const funBrushChange = (flag) => {
  167. const echartIns = toRaw(chartIns.value);
  168. echartIns.dispatchAction({
  169. type: "takeGlobalCursor",
  170. // 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
  171. key: "brush",
  172. brushOption: {
  173. seriesIndex: [1],
  174. yAxisIndex: 0,
  175. transformable: true,
  176. throttleType: "debounce",
  177. throttleDelay: 1000,
  178. removeOnClick: true,
  179. brushType: flag ? "polygon" : false,
  180. brushMode: "multiple",
  181. brushStyle: {
  182. borderWidth: 1,
  183. color: "rgba(255,36,36,0.2)",
  184. borderColor: "#ff2424",
  185. },
  186. },
  187. });
  188. echartIns.off("brushSelected");
  189. echartIns.on("brushSelected", (params) => {
  190. emits("getSelected", params.batch || []);
  191. });
  192. };
  193. watch(
  194. () => props.brush,
  195. (newVal, oldVal) => funBrushChange(newVal)
  196. );
  197. onMounted(() => {
  198. nextTick(() => {
  199. init();
  200. });
  201. });
  202. watch(
  203. () => props.echartsTheme,
  204. (newVal, oldVal) => init()
  205. );
  206. const init = () => {
  207. echarts.registerTheme("chartTheme", chartTheme);
  208. const echartIns = echarts.init(
  209. document.getElementById(chartId),
  210. props.echartsTheme
  211. );
  212. document.getElementById(chartId).removeAttribute("_echarts_instance_")
  213. ? document.getElementById(chartId).removeAttribute("_echarts_instance_")
  214. : "";
  215. chartIns.value = echartIns;
  216. echartIns.setOption(option.value);
  217. funBrushChange(props.brush);
  218. window.addEventListener("resize", () => {
  219. echartIns.resize();
  220. });
  221. };
  222. </script>
  223. <template>
  224. <div :id="chartId" :style="`height: 400px; width: ${width || '900px'}`"></div>
  225. </template>