You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
9.7 KiB

2 weeks ago
4 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
4 weeks ago
  1. <template>
  2. <!-- <div ref="qxnlzhqEchartsRef" id="qxnlzhqEcharts"></div> -->
  3. <div class="qxjmqbox">
  4. <div ref="KlineCanvs" id="qxjmqEcharts"></div>
  5. </div>
  6. </template>
  7. <script setup>
  8. import { ref, onMounted, onBeforeUnmount, toRef } from "vue";
  9. import * as echarts from "echarts";
  10. import { color } from "echarts/lib/export";
  11. defineExpose({ initQXNLZHEcharts });
  12. const KlineCanvs = ref(null);
  13. let KlineCanvsChart = null;
  14. const heatmapData = ref([]); // 存储热力图数据
  15. // 假数据
  16. const rawData2 = ref([]);
  17. const lineData3 = ref([]);
  18. function initQXNLZHEcharts(kline, qxnlzhqData) {
  19. qxnlzhqData[9][9] = 1;
  20. qxnlzhqData[2][9] = 1;
  21. rawData2.value = qxnlzhqData;
  22. // 处理热力图数据
  23. const processedHeatmap = [];
  24. rawData2.value.forEach((item, dateIndex) => {
  25. const [date, d1, d2, d3, d4, d5, d6, d7, d8, d9] = item;
  26. processedHeatmap.push([
  27. dateIndex,
  28. 0,
  29. d4,
  30. d8 == 1 ? "green" : "transparent",
  31. ]); // 数据1
  32. processedHeatmap.push([
  33. dateIndex,
  34. 1,
  35. d3,
  36. d7 == 1 ? "purple" : "transparent",
  37. ]); // 数据2
  38. processedHeatmap.push([dateIndex, 2, d2, d6 == 1 ? "red" : "transparent"]); // 数据3
  39. processedHeatmap.push([
  40. dateIndex,
  41. 3,
  42. d1,
  43. d5 == 1 ? "yellow" : "transparent",
  44. ]); // 数据4
  45. });
  46. heatmapData.value = processedHeatmap;
  47. // 处理折线图数据
  48. lineData3.value = rawData2.value.map((item) => item[9]);
  49. console.log("热力图数据:", heatmapData.value);
  50. console.log("折线图数据:", lineData3.value);
  51. const data = kline;
  52. // 切割数据方法
  53. const spliteDate = (a) => {
  54. const categoryData = [];
  55. let value = [];
  56. for (let i = 0; i < a.length; i++) {
  57. categoryData.push(a[i].splice(0, 1)[0]);
  58. value.push(a[i]);
  59. }
  60. return { categoryData, value };
  61. };
  62. const dealData = spliteDate(data);
  63. // 给配置项
  64. const KlineOption = {
  65. tooltip: {
  66. trigger: 'item', // 触发类型 坐标轴触发
  67. axisPointer: {
  68. type: 'cross', // 十字准星效果
  69. crossStyle: {
  70. color: '#999'
  71. }
  72. },
  73. formatter: function (params) {
  74. if (params.seriesType === 'candlestick') {
  75. const date = params.name
  76. // 开收低高分别取参数的第2到第5个数
  77. const open = params.data[1]
  78. const close = params.data[2]
  79. const low = params.data[3]
  80. const high = params.data[4]
  81. return `日期: ${date}<br/>开: ${open}<br/>收: ${close}<br/>低: ${low}<br/>高: ${high}`
  82. }
  83. return params.value[2]
  84. }
  85. },
  86. //控制坐标轴
  87. grid: [
  88. { top: "5%", height: "40%" },
  89. { top: "45%", height: "35%" },
  90. { top: "80%", height: "2%" },
  91. ],
  92. visualMap: [
  93. {
  94. show: false, // 不显示控制条
  95. seriesIndex: 1, // 作用于热力图的系列
  96. min: 0,
  97. max: 2000, // 根据您的数据范围调整
  98. calculable: true,
  99. orient: "horizontal",
  100. left: "center",
  101. bottom: "15%",
  102. inRange: {
  103. color: ["transparent"],
  104. },
  105. },
  106. ],
  107. // 横坐标内容
  108. xAxis: [
  109. {
  110. type: "category",
  111. gridIndex: 0,
  112. data: dealData.categoryData,
  113. axisPointer: {
  114. show: true,
  115. type: "shadow",
  116. },
  117. axisTick: { show: false }, // 隐藏刻度线
  118. axisLabel: { show: false, rotate: 45 }, // 隐藏刻度标签
  119. axisLine: {
  120. show: true,
  121. lineStyle: {
  122. color: "grey",
  123. },
  124. },
  125. },
  126. {
  127. type: "category",
  128. gridIndex: 1,
  129. data: dealData.categoryData,
  130. axisTick: { show: false }, // 隐藏刻度线
  131. axisLabel: { show: false, rotate: 45 }, // 隐藏刻度标签
  132. splitLine: {
  133. show: true,
  134. lineStyle: {
  135. color: "white",
  136. // 间隔线类型实线
  137. type: "solid",
  138. },
  139. interval: 0,
  140. },
  141. },
  142. {
  143. type: "category",
  144. gridIndex: 2,
  145. data: dealData.categoryData,
  146. axisLine: { lineStyle: { color: "#8392A5" } },
  147. },
  148. ],
  149. yAxis: [
  150. {
  151. scale: true,
  152. axisLabel: {
  153. formatter: function (value) {
  154. return value;
  155. },
  156. },
  157. axisLine: {
  158. show: true,
  159. lineStyle: { color: "#8392A5" },
  160. },
  161. splitLine: {
  162. show: false,
  163. },
  164. axisPointer: {
  165. show: true,
  166. label: {
  167. show: true,
  168. },
  169. type: "line",
  170. },
  171. },
  172. {
  173. gridIndex: 1,
  174. type: "category",
  175. data: [0, 1, 2, 3], // 倒序显示
  176. axisLine: { lineStyle: { color: "#8392A5" } },
  177. axisLabel: {
  178. show: false, // 显示刻度标签
  179. color: "#fff", // 白色文字
  180. backgroundColor: "transparent",
  181. fontSize: 12,
  182. margin: 8,
  183. },
  184. axisTick: { show: false }, // 隐藏刻度线
  185. splitLine: {
  186. show: true,
  187. lineStyle: {
  188. color: "#8392A5",
  189. width: 1,
  190. type: "solid",
  191. },
  192. interval: 0, // 强制显示间隔
  193. },
  194. },
  195. {
  196. gridIndex: 2,
  197. type: "value",
  198. axisLine: {
  199. show: true,
  200. lineStyle: { color: "#8392A5" },
  201. },
  202. splitLine: {
  203. show: !1,
  204. },
  205. axisTick: { show: false }, // 隐藏刻度线
  206. axisLabel: { show: false }, // 隐藏刻度标签
  207. },
  208. ],
  209. // 下拉条
  210. dataZoom: [
  211. {
  212. textStyle: {
  213. color: "white", // 字体颜色
  214. },
  215. handleIcon:
  216. "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z",
  217. handleSize: "80%",
  218. dataBackground: {
  219. areaStyle: {
  220. color: "#8392A5",
  221. },
  222. lineStyle: {
  223. opacity: 0.8,
  224. color: "#8392A5",
  225. },
  226. },
  227. xAxisIndex: [0, 1, 2],
  228. handleStyle: {
  229. color: "#fff",
  230. shadowBlur: 3,
  231. shadowColor: "rgba(0, 0, 0, 0.6)",
  232. shadowOffsetX: 2,
  233. shadowOffsetY: 2,
  234. },
  235. bottom: "5%", // 下移数据缩放滑块
  236. },
  237. {
  238. show: !1,
  239. type: "slider",
  240. },
  241. {
  242. type: "inside",
  243. },
  244. ],
  245. series: [
  246. {
  247. type: "candlestick",
  248. name: "\u65e5K",
  249. // 数据
  250. data: dealData.value,
  251. itemStyle: {
  252. normal: {
  253. color0: "red", // 阴线颜色
  254. color: "#0CF49B", // 阳线颜色
  255. borderColor0: "#FD1050", // 阴线边框颜色
  256. borderColor: "#0CF49B", // 阳线边框颜色
  257. },
  258. },
  259. },
  260. // 副图热力矩阵
  261. {
  262. name: "热力矩阵",
  263. type: "heatmap",
  264. gridIndex: 1,
  265. xAxisIndex: 1,
  266. yAxisIndex: 1,
  267. data: processedHeatmap,
  268. coordinateSystem: "cartesian2d",
  269. // tooltip: {
  270. // // 覆盖全局 tooltip 配置
  271. // formatter: function (params) {
  272. // const date = params.axisValue;
  273. // return `${date}:${params.data[2]}`; // 直接取数据中的第3个元素(数值)
  274. // }
  275. // },
  276. label: {
  277. normal: {
  278. show: true,
  279. color: "#fff", // 文本颜色
  280. formatter: function (params) {
  281. const value = params.value[2]; // 数值
  282. const colorType = params.value[3]; // 颜色类型
  283. // 使用 rich 富文本格式
  284. return `{${colorType}|${value}}`;
  285. },
  286. rich: {
  287. green: { color: "#27ae60", fontWeight: "bold" },
  288. purple: { color: "#8e44ad", fontWeight: "bold" },
  289. red: { color: "#FF0000", fontWeight: "bold" },
  290. yellow: { color: "#FFFF00", fontWeight: "bold" },
  291. normal: { color: "#fff" },
  292. },
  293. },
  294. },
  295. itemStyle: {
  296. normal: {
  297. color: "transparent",
  298. borderWidth: 2,
  299. },
  300. },
  301. emphasis: {
  302. itemStyle: {
  303. shadowBlur: 10,
  304. shadowColor: "rgba(0, 0, 0, 0.5)",
  305. },
  306. },
  307. },
  308. {
  309. name: "凸起",
  310. type: "line",
  311. xAxisIndex: 2,
  312. yAxisIndex: 2,
  313. data: lineData3.value,
  314. color: "black",
  315. lineStyle: {
  316. normal: {
  317. color: "red",
  318. },
  319. },
  320. symbol: "none",
  321. emphasis: {
  322. showSymbol: true,
  323. },
  324. },
  325. ],
  326. };
  327. // 创造echarts图
  328. KlineCanvsChart = echarts.init(KlineCanvs.value);
  329. KlineCanvsChart.setOption(KlineOption);
  330. // 窗口大小变化时重置图表大小
  331. window.addEventListener("resize", () => {
  332. KlineCanvsChart.resize();
  333. });
  334. }
  335. const windowHeight = ref(window.innerHeight);
  336. const updateHeight = () => {
  337. windowHeight.value = window.innerHeight; // 更新响应式变量
  338. };
  339. onMounted(() => {
  340. window.addEventListener("resize", updateHeight); // 监听窗口变化
  341. });
  342. onBeforeUnmount(() => {
  343. // 组件卸载时销毁图表
  344. if (KlineCanvsChart) {
  345. KlineCanvsChart.dispose();
  346. }
  347. });
  348. </script>
  349. <style scoped>
  350. .qxjmqbox {
  351. height: auto;
  352. width: 100%;
  353. }
  354. #qxjmqEcharts {
  355. width: 100%;
  356. height: 500px;
  357. margin-left: 1rem;
  358. top: 5rem;
  359. }
  360. /* 手机端适配样式 */
  361. @media only screen and (max-width: 768px) {
  362. #qxjmqEcharts {
  363. width: 100%;
  364. height: 400px;
  365. margin-left: 1rem;
  366. top: 5rem;
  367. }
  368. .qxjmqbox {
  369. height: auto;
  370. width: 110%;
  371. margin-top: -5rem;
  372. margin-left: -1rem;
  373. }
  374. }
  375. </style>