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.

406 lines
10 KiB

2 weeks ago
4 weeks ago
3 weeks ago
3 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. // 使用非破坏性的方法,避免修改原数组
  58. categoryData.push(a[i][0]);
  59. value.push(a[i].slice(1)); // 使用 slice 而不是 splice
  60. }
  61. return { categoryData, value };
  62. };
  63. const dealData = spliteDate(data);
  64. // 给配置项
  65. const KlineOption = {
  66. tooltip: {
  67. trigger: 'item', // 触发类型 坐标轴触发
  68. axisPointer: {
  69. type: 'cross', // 十字准星效果
  70. crossStyle: {
  71. color: '#999'
  72. }
  73. },
  74. formatter: function (params) {
  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. },
  84. //控制坐标轴
  85. grid: [
  86. { top: "5%", height: "40%" },
  87. { top: "45%", height: "35%" },
  88. { top: "80%", height: "2%" },
  89. ],
  90. visualMap: [
  91. {
  92. show: false, // 不显示控制条
  93. seriesIndex: 1, // 作用于热力图的系列
  94. min: 0,
  95. max: 2000, // 根据您的数据范围调整
  96. calculable: true,
  97. orient: "horizontal",
  98. left: "center",
  99. bottom: "15%",
  100. inRange: {
  101. color: ["transparent"],
  102. },
  103. },
  104. ],
  105. // 横坐标内容
  106. xAxis: [
  107. {
  108. type: "category",
  109. gridIndex: 0,
  110. data: dealData.categoryData,
  111. axisPointer: {
  112. show: true,
  113. type: "line",
  114. label: {
  115. show: true,
  116. backgroundColor: 'rgba(0,191,255)',
  117. color: 'black'
  118. },
  119. },
  120. axisTick: { show: false }, // 隐藏刻度线
  121. axisLabel: { show: false, rotate: 45 }, // 隐藏刻度标签
  122. axisLine: {
  123. show: true,
  124. lineStyle: {
  125. color: "white",
  126. },
  127. },
  128. },
  129. {
  130. type: "category",
  131. gridIndex: 1,
  132. data: dealData.categoryData,
  133. axisTick: { show: false }, // 隐藏刻度线
  134. axisLabel: { show: false, rotate: 45 }, // 隐藏刻度标签
  135. splitLine: {
  136. show: true,
  137. lineStyle: {
  138. color: "white",
  139. // 间隔线类型实线
  140. type: "solid",
  141. },
  142. interval: 0,
  143. },
  144. },
  145. {
  146. type: "category",
  147. gridIndex: 2,
  148. data: dealData.categoryData,
  149. axisLine: { lineStyle: { color: "white" } },
  150. },
  151. ],
  152. yAxis: [
  153. {
  154. scale: true,
  155. axisLabel: {
  156. formatter: function (value) {
  157. return value;
  158. },
  159. },
  160. axisLine: {
  161. show: true,
  162. lineStyle: { color: "white" },
  163. },
  164. splitLine: {
  165. show: false,
  166. },
  167. axisPointer: {
  168. show: true,
  169. label: {
  170. show: true,
  171. backgroundColor: 'rgba(0,255,127)',
  172. color: 'black'
  173. },
  174. type: "line",
  175. },
  176. },
  177. {
  178. gridIndex: 1,
  179. type: "category",
  180. data: [0, 1, 2, 3], // 倒序显示
  181. axisLine: { lineStyle: { color: "white" } },
  182. axisLabel: {
  183. show: false, // 显示刻度标签
  184. color: "#fff", // 白色文字
  185. backgroundColor: "transparent",
  186. fontSize: 12,
  187. margin: 8,
  188. },
  189. axisPointer: {
  190. show: true,
  191. label: {
  192. show: false,
  193. },
  194. type: "line",
  195. },
  196. axisTick: { show: false }, // 隐藏刻度线
  197. splitLine: {
  198. show: true,
  199. lineStyle: {
  200. color: "#8392A5",
  201. width: 1,
  202. type: "solid",
  203. },
  204. interval: 0, // 强制显示间隔
  205. },
  206. },
  207. {
  208. gridIndex: 2,
  209. type: "value",
  210. axisLine: {
  211. show: true,
  212. lineStyle: { color: "white" },
  213. },
  214. splitLine: {
  215. show: !1,
  216. },
  217. axisTick: { show: false }, // 隐藏刻度线
  218. axisLabel: { show: false }, // 隐藏刻度标签
  219. },
  220. ],
  221. // 下拉条
  222. dataZoom: [
  223. {
  224. textStyle: {
  225. color: "white", // 字体颜色
  226. },
  227. handleIcon:
  228. "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",
  229. handleSize: "80%",
  230. dataBackground: {
  231. areaStyle: {
  232. color: "#8392A5",
  233. },
  234. lineStyle: {
  235. opacity: 0.8,
  236. color: "#8392A5",
  237. },
  238. },
  239. xAxisIndex: [0, 1, 2],
  240. handleStyle: {
  241. color: "#fff",
  242. shadowBlur: 3,
  243. shadowColor: "rgba(0, 0, 0, 0.6)",
  244. shadowOffsetX: 2,
  245. shadowOffsetY: 2,
  246. },
  247. bottom: "5%", // 下移数据缩放滑块
  248. },
  249. {
  250. show: !1,
  251. type: "slider",
  252. },
  253. {
  254. type: "inside",
  255. },
  256. ],
  257. series: [
  258. {
  259. type: "candlestick",
  260. name: "\u65e5K",
  261. // 数据
  262. data: dealData.value,
  263. itemStyle: {
  264. normal: {
  265. color0: "red", // 阴线颜色
  266. color: "#0CF49B", // 阳线颜色
  267. borderColor0: "#FD1050", // 阴线边框颜色
  268. borderColor: "#0CF49B", // 阳线边框颜色
  269. },
  270. },
  271. },
  272. // 副图热力矩阵
  273. {
  274. name: "热力矩阵",
  275. type: "heatmap",
  276. gridIndex: 1,
  277. xAxisIndex: 1,
  278. yAxisIndex: 1,
  279. data: processedHeatmap,
  280. coordinateSystem: "cartesian2d",
  281. tooltip: {
  282. trigger: "item",
  283. axisPointer: {
  284. type: 'cross', // 十字准星效果
  285. crossStyle: {
  286. color: '#999'
  287. }
  288. },
  289. // 覆盖全局 tooltip 配置
  290. formatter: function (params) {
  291. return `${params.value[2]}`; // 直接取数据中的第3个元素(数值)
  292. }
  293. },
  294. label: {
  295. normal: {
  296. show: true,
  297. color: "#fff", // 文本颜色
  298. formatter: function (params) {
  299. const value = params.value[2]; // 数值
  300. const colorType = params.value[3]; // 颜色类型
  301. // 使用 rich 富文本格式
  302. return `{${colorType}|${value}}`;
  303. },
  304. rich: {
  305. green: { color: "#27ae60", fontWeight: "bold" },
  306. purple: { color: "#8e44ad", fontWeight: "bold" },
  307. red: { color: "#FF0000", fontWeight: "bold" },
  308. yellow: { color: "#FFFF00", fontWeight: "bold" },
  309. normal: { color: "#fff" },
  310. },
  311. },
  312. },
  313. itemStyle: {
  314. normal: {
  315. color: "transparent",
  316. borderWidth: 2,
  317. },
  318. },
  319. emphasis: {
  320. itemStyle: {
  321. shadowBlur: 10,
  322. shadowColor: "rgba(0, 0, 0, 0.5)",
  323. },
  324. },
  325. },
  326. {
  327. name: "凸起",
  328. type: "line",
  329. xAxisIndex: 2,
  330. yAxisIndex: 2,
  331. data: lineData3.value,
  332. color: "black",
  333. lineStyle: {
  334. normal: {
  335. color: "red",
  336. },
  337. },
  338. symbol: "none",
  339. emphasis: {
  340. showSymbol: true,
  341. },
  342. },
  343. ],
  344. };
  345. // 创造echarts图
  346. KlineCanvsChart = echarts.init(KlineCanvs.value);
  347. KlineCanvsChart.setOption(KlineOption);
  348. // 窗口大小变化时重置图表大小
  349. window.addEventListener("resize", () => {
  350. KlineCanvsChart.resize();
  351. });
  352. }
  353. const windowHeight = ref(window.innerHeight);
  354. const updateHeight = () => {
  355. windowHeight.value = window.innerHeight; // 更新响应式变量
  356. };
  357. onMounted(() => {
  358. window.addEventListener("resize", updateHeight); // 监听窗口变化
  359. });
  360. onBeforeUnmount(() => {
  361. // 组件卸载时销毁图表
  362. if (KlineCanvsChart) {
  363. KlineCanvsChart.dispose();
  364. }
  365. });
  366. </script>
  367. <style scoped>
  368. .qxjmqbox {
  369. height: auto;
  370. width: 100%;
  371. }
  372. #qxjmqEcharts {
  373. width: 130%;
  374. height: 800px;
  375. margin-left: -15%;
  376. top: 5rem;
  377. }
  378. /* 手机端适配样式 */
  379. @media only screen and (max-width: 768px) {
  380. #qxjmqEcharts {
  381. width: 100%;
  382. height: 400px;
  383. margin-left: -6%;
  384. top: 5rem;
  385. }
  386. .qxjmqbox {
  387. height: auto;
  388. width: 130%;
  389. margin-top: -5rem;
  390. margin-left: -1rem;
  391. }
  392. }
  393. </style>