cursorReferenceMixin.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // cursorReferenceMixin.js
  2. // import * as echarts from "echarts";
  3. export default {
  4. data() {
  5. return {
  6. // 参考线相关数据
  7. cursorHightPoints: [], // 存储所有参考线
  8. currentCursorIndex: -1, // 当前参考线索引
  9. peakPoints: [], // 存储所有峰值点
  10. isHandlingCursor: false, // 防止重复处理
  11. chartInstance: null, // ECharts实例
  12. };
  13. },
  14. mounted() {
  15. // 监听键盘事件
  16. window.addEventListener("keydown", this.handleKeyDown);
  17. },
  18. beforeDestroy() {
  19. // 移除事件监听
  20. window.removeEventListener("keydown", this.handleKeyDown);
  21. },
  22. methods: {
  23. /**
  24. * 处理按钮点击生成参考线
  25. */
  26. handleMoveCursor() {
  27. console.log("handleMoveCursor", "222");
  28. if (this.isHandlingCursor || !this.envelopeList) return;
  29. this.isHandlingCursor = true;
  30. // 1. 找到所有峰值点
  31. this.findPeakPoints();
  32. // 2. 如果没有峰值点则返回
  33. if (this.peakPoints.length === 0) {
  34. this.isHandlingCursor = false;
  35. return;
  36. }
  37. console.log(this.peakPoints);
  38. // 3. 找到Y轴最大值点
  39. const maxPeak = this.peakPoints.reduce((prev, current) =>
  40. prev.y > current.y ? prev : current
  41. );
  42. // 4. 创建参考线数据
  43. const referenceLine = {
  44. xAxis: maxPeak.x,
  45. val: maxPeak.y.toFixed(9),
  46. index: maxPeak.index,
  47. };
  48. // 5. 更新参考线
  49. this.cursorHightPoints = [referenceLine];
  50. this.currentCursorIndex = this.peakPoints.findIndex(
  51. (p) => p.index === maxPeak.index
  52. );
  53. // 6. 更新图表
  54. this.updateCursorElements2();
  55. this.isHandlingCursor = false;
  56. },
  57. /**
  58. * 查找所有峰值点
  59. */
  60. findPeakPoints() {
  61. this.peakPoints = [];
  62. const yValues = this.envelopeList.y;
  63. const xValues = this.envelopeList.x;
  64. // 1. 找到所有局部峰值点(比相邻点都高的点)
  65. const allPeaks = [];
  66. for (let i = 1; i < yValues.length - 1; i++) {
  67. if (yValues[i] > yValues[i - 1] && yValues[i] > yValues[i + 1]) {
  68. allPeaks.push({
  69. x: xValues[i],
  70. y: yValues[i],
  71. index: i,
  72. });
  73. }
  74. }
  75. // 2. 按y值从大到小排序
  76. allPeaks.sort((a, b) => b.y - a.y);
  77. this.peakPoints = allPeaks;
  78. },
  79. /**
  80. * 处理键盘事件
  81. */
  82. handleKeyDown(event) {
  83. if (this.cursorHightPoints.length === 0) return;
  84. switch (event.keyCode) {
  85. case 37: // 左箭头
  86. this.moveCursorToLeft();
  87. break;
  88. case 39: // 右箭头
  89. this.moveCursorToRight();
  90. break;
  91. default:
  92. return;
  93. }
  94. // 阻止默认行为
  95. event.preventDefault();
  96. },
  97. /**
  98. * 向左移动参考线并保持居中
  99. */
  100. moveCursorToLeft() {
  101. this.findPeakPoints();
  102. if (this.currentCursorIndex <= 0) return;
  103. const newIndex = this.currentCursorIndex - 1;
  104. const newPeak = this.peakPoints[newIndex];
  105. this.updateCursorPosition(newPeak, newIndex);
  106. this.centerViewOnPeak(newPeak);
  107. },
  108. /**
  109. * 向右移动参考线并保持居中
  110. */
  111. moveCursorToRight() {
  112. this.findPeakPoints();
  113. if (this.currentCursorIndex >= this.peakPoints.length - 1) return;
  114. const newIndex = this.currentCursorIndex + 1;
  115. const newPeak = this.peakPoints[newIndex];
  116. this.updateCursorPosition(newPeak, newIndex);
  117. // this.centerViewOnPeak(newPeak);
  118. },
  119. /**
  120. * 将视图中心对准峰值点
  121. */
  122. centerViewOnPeak(peak) {
  123. if (!this.chartInstance || !peak) return;
  124. // 获取当前x轴配置和数据范围
  125. const option = this.chartInstance.getOption();
  126. const xAxis = option.xAxis[0];
  127. // 计算当前可视范围
  128. const axisModel = this.chartInstance.getModel().getComponent("xAxis");
  129. const currentRange = axisModel.axis.scale.getExtent();
  130. const viewWidth = currentRange[1] - currentRange[0];
  131. // 计算新的居中范围(确保不超出数据边界)
  132. const newMin = Math.max(xAxis.min, peak.x - viewWidth / 2);
  133. const newMax = Math.min(xAxis.max, peak.x + viewWidth / 2);
  134. // 应用新的视图范围
  135. this.chartInstance.dispatchAction({
  136. type: "dataZoom",
  137. xAxisIndex: 0,
  138. start: ((newMin - xAxis.min) / (xAxis.max - xAxis.min)) * 100,
  139. end: ((newMax - xAxis.min) / (xAxis.max - xAxis.min)) * 100,
  140. animation: {
  141. duration: 300, // 添加平滑过渡效果
  142. },
  143. });
  144. },
  145. /**
  146. * 更新参考线位置
  147. */
  148. updateCursorPosition(peak, index) {
  149. this.cursorHightPoints = [
  150. {
  151. xAxis: peak.x,
  152. val: peak.y.toFixed(9),
  153. index: peak.index,
  154. },
  155. ];
  156. console.log(this.cursorHightPoints, "updateCursorPosition");
  157. this.currentCursorIndex = index;
  158. this.$nextTick(() => {
  159. this.updateCursorElements2();
  160. });
  161. },
  162. /**
  163. * 更新参考线元素(不覆盖已有参考线)
  164. */
  165. updateCursorElements2() {
  166. if (!this.chartInstance) return;
  167. // 1. 获取当前图表配置中的已有series
  168. const currentOption = this.chartInstance.getOption();
  169. const existingSeries = currentOption.series || [];
  170. // 2. 过滤掉旧的峰值参考线(通过id或特定标记识别)
  171. const filteredSeries = existingSeries.filter(
  172. (series) => !series.id || !series.id.includes("PEAK_REFERENCE_LINE")
  173. );
  174. console.log(filteredSeries);
  175. // 3. 准备新的峰值参考线配置
  176. const cursorHighLineSeries = {
  177. id: "PEAK_REFERENCE_LINE",
  178. type: "line",
  179. markLine: {
  180. data: this.cursorHightPoints.map((point) => ({
  181. xAxis: point.xAxis,
  182. label: {
  183. formatter: "峰值: " + point.val,
  184. },
  185. lineStyle: {
  186. color: "#FF0000",
  187. },
  188. })),
  189. },
  190. };
  191. // 4. 合并所有series配置
  192. const allSeries = [
  193. ...filteredSeries, // 保留已有series
  194. cursorHighLineSeries, // 添加新的峰值参考线
  195. ];
  196. console.log(allSeries);
  197. // 5. 更新图表配置
  198. this.chartInstance.setOption(
  199. {
  200. series: allSeries,
  201. },
  202. {
  203. replaceMerge: ["series"],
  204. notMerge: false,
  205. }
  206. );
  207. },
  208. /**
  209. * 获取参考线markLine配置
  210. */
  211. getCursorMarkLineConfig() {
  212. return {
  213. data: this.cursorHightPoints.map((point) => ({
  214. xAxis: point.xAxis,
  215. label: {
  216. formatter: "峰值: " + point.val,
  217. },
  218. lineStyle: {
  219. color: "#FF0000",
  220. },
  221. })),
  222. symbol: ["none", "none"],
  223. silent: true,
  224. };
  225. },
  226. removeCursor() {
  227. if (!this.chartInstance) return;
  228. // 获取当前图表配置中的所有series
  229. const currentOption = this.chartInstance.getOption();
  230. const existingSeries = currentOption.series || [];
  231. // 过滤掉峰值参考线(通过id或特定标记识别)
  232. const filteredSeries = existingSeries.filter(
  233. (series) => !series.id || !series.id.includes("PEAK_REFERENCE_LINE")
  234. );
  235. // 更新图表配置,移除所有峰值参考线
  236. this.chartInstance.setOption(
  237. {
  238. series: filteredSeries,
  239. },
  240. {
  241. replaceMerge: ["series"],
  242. notMerge: false,
  243. }
  244. );
  245. // 清空当前光标数据
  246. this.cursorHightPoints = [];
  247. this.currentCursorIndex = -1;
  248. },
  249. },
  250. };