kd-lane-chart-v3 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +1040 -570
- package/dist/esm/index.js.map +1 -1
- package/dist/kd-lane-chart-v3.css +59 -59
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -2659,7 +2659,7 @@ function findLogTrendSeries(chart, paramId) {
|
|
|
2659
2659
|
const type = sm && sm.subType || (Array.isArray(opt.type) ? opt.type[0] : opt.type);
|
|
2660
2660
|
if (type !== "line") continue;
|
|
2661
2661
|
const name = Array.isArray(sm.name) ? sm.name[0] : sm.name;
|
|
2662
|
-
if (name === "helper" || name === "log-grid") continue;
|
|
2662
|
+
if (name === "helper" || name === "log-grid" || name === "trend") continue;
|
|
2663
2663
|
const pid = Array.isArray(opt.paramId) ? opt.paramId[0] : opt.paramId;
|
|
2664
2664
|
if (String(pid) === String(paramId)) return opt;
|
|
2665
2665
|
}
|
|
@@ -2718,6 +2718,17 @@ function logTrendDataToPixel(chart, paramId, lg, depth) {
|
|
|
2718
2718
|
const series = findLogTrendSeries(chart, paramId);
|
|
2719
2719
|
const xAxisIndex = series ? axisIndexOf$1(series.xAxisIndex) : 0;
|
|
2720
2720
|
const yAxisIndex = series ? axisIndexOf$1(series.yAxisIndex) : 0;
|
|
2721
|
+
try {
|
|
2722
|
+
const model = chart.getModel();
|
|
2723
|
+
const xAxis = model.getComponent("xAxis", xAxisIndex) && model.getComponent("xAxis", xAxisIndex).axis;
|
|
2724
|
+
const yAxis = model.getComponent("yAxis", yAxisIndex) && model.getComponent("yAxis", yAxisIndex).axis;
|
|
2725
|
+
if (xAxis && yAxis) {
|
|
2726
|
+
const x = xAxis.toGlobalCoord(xAxis.dataToCoord(lg, true));
|
|
2727
|
+
const y = yAxis.toGlobalCoord(yAxis.dataToCoord(depth, true));
|
|
2728
|
+
if (Number.isFinite(x) && Number.isFinite(y)) return [x, y];
|
|
2729
|
+
}
|
|
2730
|
+
} catch (e) {
|
|
2731
|
+
}
|
|
2721
2732
|
try {
|
|
2722
2733
|
const px = chart.convertToPixel({ xAxisIndex, yAxisIndex }, [lg, depth]);
|
|
2723
2734
|
if (px && Number.isFinite(px[0]) && Number.isFinite(px[1])) return px;
|
|
@@ -3344,7 +3355,6 @@ const TREND_MIRROR_POINT_STYLE = {
|
|
|
3344
3355
|
lineWidth: 1
|
|
3345
3356
|
};
|
|
3346
3357
|
const TREND_LINE_Z = 9999;
|
|
3347
|
-
const TREND_POINT_Z = 99999;
|
|
3348
3358
|
const DEPTH_EDGE_SNAP = 0.2;
|
|
3349
3359
|
const TREND_CLICK_DELAY_MS = 240;
|
|
3350
3360
|
const TREND_HIT_RADIUS = 14;
|
|
@@ -3699,7 +3709,7 @@ function listLineSeries(model) {
|
|
|
3699
3709
|
const type = sm && sm.subType || seriesTypeName(opt);
|
|
3700
3710
|
if (type !== "line") continue;
|
|
3701
3711
|
const name = optionScalar(sm && sm.name) || seriesDisplayName(opt);
|
|
3702
|
-
if (name === "helper" || name === "log-grid") continue;
|
|
3712
|
+
if (name === "helper" || name === "log-grid" || name === "trend") continue;
|
|
3703
3713
|
out.push({
|
|
3704
3714
|
seriesIndex: sm.seriesIndex,
|
|
3705
3715
|
xAxisIndex: axisIndexOf(opt.xAxisIndex),
|
|
@@ -3738,20 +3748,27 @@ function findSeriesForDepth(chart, paramId, depth) {
|
|
|
3738
3748
|
function eventOffsetInChart(chart, evt) {
|
|
3739
3749
|
var _a, _b;
|
|
3740
3750
|
const zr = chart.getZr();
|
|
3741
|
-
const
|
|
3742
|
-
|
|
3743
|
-
|
|
3751
|
+
const clamp = (x, y) => ({
|
|
3752
|
+
offsetX: Math.max(0, Math.min(x, zr.getWidth())),
|
|
3753
|
+
offsetY: Math.max(0, Math.min(y, zr.getHeight()))
|
|
3754
|
+
});
|
|
3755
|
+
if (evt && evt.event && Number.isFinite(evt.offsetX) && Number.isFinite(evt.offsetY)) {
|
|
3756
|
+
return clamp(evt.offsetX, evt.offsetY);
|
|
3757
|
+
}
|
|
3744
3758
|
const native = (evt == null ? void 0 : evt.event) || evt;
|
|
3759
|
+
let el = null;
|
|
3760
|
+
try {
|
|
3761
|
+
el = zr.painter && zr.painter.getViewportRoot && zr.painter.getViewportRoot();
|
|
3762
|
+
} catch (e) {
|
|
3763
|
+
}
|
|
3764
|
+
const rect = (_b = (_a = el || chart.getDom()) == null ? void 0 : _a.getBoundingClientRect) == null ? void 0 : _b.call(_a);
|
|
3745
3765
|
if (rect && Number.isFinite(native == null ? void 0 : native.clientX) && Number.isFinite(native == null ? void 0 : native.clientY)) {
|
|
3746
|
-
|
|
3747
|
-
offsetY = native.clientY - rect.top;
|
|
3748
|
-
} else if (Number.isFinite(evt == null ? void 0 : evt.offsetX) && Number.isFinite(evt == null ? void 0 : evt.offsetY)) {
|
|
3749
|
-
offsetX = evt.offsetX;
|
|
3750
|
-
offsetY = evt.offsetY;
|
|
3766
|
+
return clamp(native.clientX - rect.left, native.clientY - rect.top);
|
|
3751
3767
|
}
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3768
|
+
if (Number.isFinite(evt == null ? void 0 : evt.offsetX) && Number.isFinite(evt == null ? void 0 : evt.offsetY)) {
|
|
3769
|
+
return clamp(evt.offsetX, evt.offsetY);
|
|
3770
|
+
}
|
|
3771
|
+
return clamp(0, 0);
|
|
3755
3772
|
}
|
|
3756
3773
|
function isPointerInAnyGrid(chart, offsetX, offsetY) {
|
|
3757
3774
|
const gridCount = modelGridCount(chartModel(chart));
|
|
@@ -3819,8 +3836,48 @@ function pixelToData(chart, paramId, offsetX, offsetY, loose = false) {
|
|
|
3819
3836
|
}
|
|
3820
3837
|
return null;
|
|
3821
3838
|
}
|
|
3839
|
+
function axisPairToPixel(chart, xAxisIndex, yAxisIndex, value, depth) {
|
|
3840
|
+
try {
|
|
3841
|
+
const model = chartModel(chart);
|
|
3842
|
+
if (!model) return null;
|
|
3843
|
+
const xComp = model.getComponent("xAxis", xAxisIndex || 0);
|
|
3844
|
+
const yComp = model.getComponent("yAxis", yAxisIndex || 0);
|
|
3845
|
+
const xAxis = xComp && xComp.axis;
|
|
3846
|
+
const yAxis = yComp && yComp.axis;
|
|
3847
|
+
if (!xAxis || !yAxis) return null;
|
|
3848
|
+
const x = xAxis.toGlobalCoord(xAxis.dataToCoord(value, true));
|
|
3849
|
+
const y = yAxis.toGlobalCoord(yAxis.dataToCoord(depth, true));
|
|
3850
|
+
if (Number.isFinite(x) && Number.isFinite(y)) return [x, y];
|
|
3851
|
+
} catch (e) {
|
|
3852
|
+
}
|
|
3853
|
+
return null;
|
|
3854
|
+
}
|
|
3855
|
+
function axisPairFromPixel(chart, xAxisIndex, yAxisIndex, offsetX, offsetY) {
|
|
3856
|
+
try {
|
|
3857
|
+
const model = chartModel(chart);
|
|
3858
|
+
if (!model) return null;
|
|
3859
|
+
const xComp = model.getComponent("xAxis", xAxisIndex || 0);
|
|
3860
|
+
const yComp = model.getComponent("yAxis", yAxisIndex || 0);
|
|
3861
|
+
const xAxis = xComp && xComp.axis;
|
|
3862
|
+
const yAxis = yComp && yComp.axis;
|
|
3863
|
+
if (!xAxis || !yAxis) return null;
|
|
3864
|
+
const value = xAxis.coordToData(xAxis.toLocalCoord(offsetX), true);
|
|
3865
|
+
const depth = yAxis.coordToData(yAxis.toLocalCoord(offsetY), true);
|
|
3866
|
+
if (!Number.isFinite(value) || !Number.isFinite(depth)) return null;
|
|
3867
|
+
return {
|
|
3868
|
+
value,
|
|
3869
|
+
depth,
|
|
3870
|
+
xAxisIndex: xAxisIndex || 0,
|
|
3871
|
+
yAxisIndex: yAxisIndex || 0
|
|
3872
|
+
};
|
|
3873
|
+
} catch (e) {
|
|
3874
|
+
return null;
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3822
3877
|
function dataToPixel(chart, paramId, value, depth) {
|
|
3823
3878
|
const finder = findSeriesForDepth(chart, paramId, depth);
|
|
3879
|
+
const live = axisPairToPixel(chart, finder.xAxisIndex, finder.yAxisIndex, value, depth);
|
|
3880
|
+
if (live) return live;
|
|
3824
3881
|
const finders = [
|
|
3825
3882
|
{ xAxisIndex: finder.xAxisIndex, yAxisIndex: finder.yAxisIndex },
|
|
3826
3883
|
{ seriesIndex: finder.seriesIndex },
|
|
@@ -3871,49 +3928,62 @@ class TrendLineManager {
|
|
|
3871
3928
|
this.dragSession = null;
|
|
3872
3929
|
this._panLockedByHover = false;
|
|
3873
3930
|
this._raf = null;
|
|
3874
|
-
this.
|
|
3875
|
-
this.
|
|
3876
|
-
this._zoomEndTimer = null;
|
|
3877
|
-
this._graphicIds = /* @__PURE__ */ Object.create(null);
|
|
3878
|
-
this._zrElCache = /* @__PURE__ */ new WeakMap();
|
|
3931
|
+
this._seriesIds = /* @__PURE__ */ Object.create(null);
|
|
3932
|
+
this._graphicCleared = /* @__PURE__ */ new WeakSet();
|
|
3879
3933
|
this._ignoreClickUntil = 0;
|
|
3934
|
+
this._destroyed = false;
|
|
3880
3935
|
}
|
|
3881
3936
|
destroy() {
|
|
3937
|
+
this._destroyed = true;
|
|
3882
3938
|
this._clearClickTimer();
|
|
3883
|
-
|
|
3884
|
-
|
|
3939
|
+
try {
|
|
3940
|
+
this._unbindDragWindow();
|
|
3941
|
+
} catch (e) {
|
|
3942
|
+
}
|
|
3943
|
+
this._panLockedByHover = false;
|
|
3944
|
+
Array.from(this.binds.keys()).forEach((laneId) => {
|
|
3945
|
+
try {
|
|
3946
|
+
this.unbindChart(laneId);
|
|
3947
|
+
} catch (e) {
|
|
3948
|
+
}
|
|
3949
|
+
});
|
|
3885
3950
|
if (this._raf) {
|
|
3886
3951
|
cancelAnimationFrame(this._raf);
|
|
3887
3952
|
this._raf = null;
|
|
3888
3953
|
}
|
|
3889
|
-
if (this._zoomRaf) {
|
|
3890
|
-
cancelAnimationFrame(this._zoomRaf);
|
|
3891
|
-
this._zoomRaf = null;
|
|
3892
|
-
}
|
|
3893
|
-
if (this._zoomEndTimer) {
|
|
3894
|
-
clearTimeout(this._zoomEndTimer);
|
|
3895
|
-
this._zoomEndTimer = null;
|
|
3896
|
-
}
|
|
3897
3954
|
this.store = /* @__PURE__ */ Object.create(null);
|
|
3898
|
-
this.
|
|
3955
|
+
this._seriesIds = /* @__PURE__ */ Object.create(null);
|
|
3956
|
+
this.binds.clear();
|
|
3957
|
+
this.host = null;
|
|
3958
|
+
}
|
|
3959
|
+
_alive() {
|
|
3960
|
+
return !this._destroyed && !!this.host;
|
|
3899
3961
|
}
|
|
3900
3962
|
/** 从模板 line.trendSegments 回显;已有 store 的曲线不覆盖,避免编辑中被模板刷新冲掉。8.21 */
|
|
3901
3963
|
hydrateFromTemplate(template) {
|
|
3964
|
+
if (!this._alive()) return;
|
|
3965
|
+
const hasEcho = Array.isArray(this.host.lineListData) && this.host.lineListData.length;
|
|
3902
3966
|
const lanes = template && template.lanes || [];
|
|
3967
|
+
const alive = /* @__PURE__ */ new Set();
|
|
3903
3968
|
lanes.forEach((lane) => {
|
|
3904
3969
|
(lane.lines || []).forEach((line) => {
|
|
3905
3970
|
if (!lane.laneId || !line.paramId) return;
|
|
3906
3971
|
const key = makeTrendKey(lane.laneId, line.paramId);
|
|
3972
|
+
alive.add(key);
|
|
3907
3973
|
if (this.store[key]) return;
|
|
3908
|
-
if (line.trendSegments
|
|
3909
|
-
this.store[key] = { segments: this._prepareEchoSegments(line.paramId, line.trendSegments) };
|
|
3910
|
-
} else {
|
|
3974
|
+
if (!hasEcho || !line.trendSegments || !line.trendSegments.length) {
|
|
3911
3975
|
this.store[key] = { segments: [] };
|
|
3976
|
+
return;
|
|
3912
3977
|
}
|
|
3978
|
+
this.store[key] = { segments: this._prepareEchoSegments(line.paramId, line.trendSegments) };
|
|
3913
3979
|
});
|
|
3914
3980
|
});
|
|
3981
|
+
Object.keys(this.store).forEach((key) => {
|
|
3982
|
+
if (!alive.has(key)) delete this.store[key];
|
|
3983
|
+
});
|
|
3915
3984
|
}
|
|
3916
3985
|
getChart(laneId) {
|
|
3986
|
+
if (!this._alive()) return null;
|
|
3917
3987
|
const ref = this.host.getChartRefByLaneId(laneId);
|
|
3918
3988
|
const chart = ref && ref.chart;
|
|
3919
3989
|
if (!chart || chart.isDisposed()) return null;
|
|
@@ -3921,6 +3991,7 @@ class TrendLineManager {
|
|
|
3921
3991
|
}
|
|
3922
3992
|
/** isDraw 可编辑,或已有控制点(只读回显)的曲线。8.21 */
|
|
3923
3993
|
listDrawableTargets() {
|
|
3994
|
+
if (!this._alive()) return [];
|
|
3924
3995
|
const lanes = this.host.currentTemplate && this.host.currentTemplate.lanes || [];
|
|
3925
3996
|
const list = [];
|
|
3926
3997
|
lanes.forEach((lane) => {
|
|
@@ -3982,45 +4053,62 @@ class TrendLineManager {
|
|
|
3982
4053
|
/** 捕获阶段监听 mousedown,保证拖控制点比图表其它逻辑先拿到。8.21 */
|
|
3983
4054
|
bindChart(laneId, chart) {
|
|
3984
4055
|
this.unbindChart(laneId);
|
|
3985
|
-
if (!chart || chart.isDisposed()) return;
|
|
3986
|
-
const onMouseDown = (e) => this.onMouseDown(e, laneId);
|
|
4056
|
+
if (!this._alive() || !chart || chart.isDisposed()) return;
|
|
3987
4057
|
const onZrDown = (e) => this.onZrMouseDown(e, laneId);
|
|
3988
4058
|
const onZrMove = (e) => this.onZrHover(e, laneId);
|
|
3989
4059
|
const onDblClick = (e) => this.handleDblClick(e, laneId);
|
|
3990
|
-
const dom = chart.getDom();
|
|
3991
|
-
if (dom) dom.addEventListener("mousedown", onMouseDown, true);
|
|
3992
4060
|
const zr = chart.getZr();
|
|
3993
4061
|
zr.on("mousedown", onZrDown);
|
|
3994
4062
|
zr.on("mousemove", onZrMove);
|
|
3995
4063
|
zr.on("dblclick", onDblClick);
|
|
3996
4064
|
const onZoom = () => {
|
|
4065
|
+
if (this.host && this.host._isPanning) return;
|
|
3997
4066
|
if (this.host && typeof this.host.startChartZoom === "function") {
|
|
3998
4067
|
this.host.startChartZoom();
|
|
3999
4068
|
}
|
|
4000
|
-
this.scheduleZoomRender();
|
|
4001
4069
|
};
|
|
4002
4070
|
if (typeof chart.on === "function") chart.on("datazoom", onZoom);
|
|
4003
|
-
this.binds.set(laneId, { chart,
|
|
4071
|
+
this.binds.set(laneId, { chart, onZrDown, onZrMove, onDblClick, onZoom, dom: chart.getDom() });
|
|
4004
4072
|
this.updateCursor(laneId);
|
|
4005
4073
|
}
|
|
4006
4074
|
unbindChart(laneId) {
|
|
4007
4075
|
const bind = this.binds.get(laneId);
|
|
4008
4076
|
if (!bind) return;
|
|
4077
|
+
const session = this.dragSession;
|
|
4078
|
+
if (session && (session.chart === bind.chart || session.target && session.target.laneId === laneId)) {
|
|
4079
|
+
this._unbindDragWindow();
|
|
4080
|
+
}
|
|
4009
4081
|
if (bind.dom && bind.onMouseDown) {
|
|
4010
4082
|
bind.dom.removeEventListener("mousedown", bind.onMouseDown, true);
|
|
4011
4083
|
}
|
|
4012
4084
|
if (bind.dom && bind.onZoom) {
|
|
4013
4085
|
bind.dom.removeEventListener("wheel", bind.onZoom);
|
|
4014
4086
|
}
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
if (
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4087
|
+
const chart = bind.chart;
|
|
4088
|
+
try {
|
|
4089
|
+
if (chart && typeof chart.getZr === "function") {
|
|
4090
|
+
const zr = chart.getZr();
|
|
4091
|
+
if (zr) {
|
|
4092
|
+
if (bind.onZrDown) zr.off("mousedown", bind.onZrDown);
|
|
4093
|
+
if (bind.onZrMove) zr.off("mousemove", bind.onZrMove);
|
|
4094
|
+
if (bind.onDblClick) zr.off("dblclick", bind.onDblClick);
|
|
4095
|
+
if (bind.onZoom) zr.off("mousewheel", bind.onZoom);
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
if (chart && bind.onZoom && typeof chart.off === "function") {
|
|
4099
|
+
chart.off("datazoom", bind.onZoom);
|
|
4023
4100
|
}
|
|
4101
|
+
} catch (e) {
|
|
4102
|
+
}
|
|
4103
|
+
delete this._seriesIds[laneId];
|
|
4104
|
+
if (bind) {
|
|
4105
|
+
bind.chart = null;
|
|
4106
|
+
bind.dom = null;
|
|
4107
|
+
bind.onZrDown = null;
|
|
4108
|
+
bind.onZrMove = null;
|
|
4109
|
+
bind.onDblClick = null;
|
|
4110
|
+
bind.onZoom = null;
|
|
4111
|
+
bind.onMouseDown = null;
|
|
4024
4112
|
}
|
|
4025
4113
|
this.binds.delete(laneId);
|
|
4026
4114
|
}
|
|
@@ -4041,10 +4129,11 @@ class TrendLineManager {
|
|
|
4041
4129
|
/** 图表重绘后对齐叠加层;拖拽中跳过,避免和 _onDragMove 抢 setOption。8.21 */
|
|
4042
4130
|
// 只排一帧,不再连刷两次 renderAll(会闪)。8.24
|
|
4043
4131
|
scheduleRender() {
|
|
4044
|
-
if (this.dragSession) return;
|
|
4132
|
+
if (!this._alive() || this.dragSession) return;
|
|
4045
4133
|
if (this._raf) return;
|
|
4046
4134
|
this._raf = requestAnimationFrame(() => {
|
|
4047
4135
|
this._raf = null;
|
|
4136
|
+
if (!this._alive()) return;
|
|
4048
4137
|
this.renderAll();
|
|
4049
4138
|
});
|
|
4050
4139
|
}
|
|
@@ -4057,385 +4146,338 @@ class TrendLineManager {
|
|
|
4057
4146
|
}
|
|
4058
4147
|
return false;
|
|
4059
4148
|
}
|
|
4060
|
-
|
|
4149
|
+
// 趋势线已是笛卡尔 series,dataZoom 带着走;这些入口留给旧调用方,不再像素跟帧。8.25
|
|
4061
4150
|
scheduleZoomRender() {
|
|
4062
|
-
if (this.dragSession || !this.hasAnyKnots()) return;
|
|
4063
|
-
this._zoomPending = true;
|
|
4064
|
-
if (this._zoomEndTimer) clearTimeout(this._zoomEndTimer);
|
|
4065
|
-
this._zoomEndTimer = setTimeout(() => {
|
|
4066
|
-
this._zoomPending = false;
|
|
4067
|
-
if (this._zoomRaf) {
|
|
4068
|
-
cancelAnimationFrame(this._zoomRaf);
|
|
4069
|
-
this._zoomRaf = null;
|
|
4070
|
-
}
|
|
4071
|
-
this.scheduleRender();
|
|
4072
|
-
}, 140);
|
|
4073
|
-
if (this._zoomRaf) return;
|
|
4074
|
-
const tick = () => {
|
|
4075
|
-
if (this.dragSession) {
|
|
4076
|
-
this._zoomRaf = null;
|
|
4077
|
-
return;
|
|
4078
|
-
}
|
|
4079
|
-
this._patchAllPositions();
|
|
4080
|
-
if (this._zoomPending) {
|
|
4081
|
-
this._zoomRaf = requestAnimationFrame(tick);
|
|
4082
|
-
} else {
|
|
4083
|
-
this._zoomRaf = null;
|
|
4084
|
-
}
|
|
4085
|
-
};
|
|
4086
|
-
this._zoomRaf = requestAnimationFrame(tick);
|
|
4087
4151
|
}
|
|
4088
|
-
|
|
4089
|
-
_patchAllPositions() {
|
|
4090
|
-
const lanes = this.host.currentTemplate && this.host.currentTemplate.lanes || [];
|
|
4091
|
-
lanes.forEach((lane) => this._patchLanePositions(lane.laneId));
|
|
4152
|
+
beginPanFollow() {
|
|
4092
4153
|
}
|
|
4093
|
-
|
|
4094
|
-
const chart = this.getChart(laneId);
|
|
4095
|
-
if (!chart) return;
|
|
4096
|
-
const targets = this.listDrawableTargets().filter((t) => t.laneId === laneId);
|
|
4097
|
-
const hasKnots = targets.some((t) => (t.segments || []).some((s) => (s.knots || []).length));
|
|
4098
|
-
if (!hasKnots) return;
|
|
4099
|
-
const patches = [];
|
|
4100
|
-
targets.forEach((target) => {
|
|
4101
|
-
patches.push(...this._buildPatches(chart, target));
|
|
4102
|
-
});
|
|
4103
|
-
if (!patches.length) return;
|
|
4104
|
-
if (!this._applyPatchesViaZr(chart, patches) && !this._zoomPending) {
|
|
4105
|
-
this.renderLane(laneId);
|
|
4106
|
-
}
|
|
4154
|
+
tickPanFollow() {
|
|
4107
4155
|
}
|
|
4108
|
-
|
|
4109
|
-
const patches = [];
|
|
4110
|
-
const { paramId, key, segments, line } = target;
|
|
4111
|
-
const canMirror = this._canMirror(line, segments);
|
|
4112
|
-
segments.forEach((seg) => {
|
|
4113
|
-
const knots = seg.knots || [];
|
|
4114
|
-
for (let i = 0; i < knots.length - 1; i++) {
|
|
4115
|
-
const p1 = knots[i];
|
|
4116
|
-
const p2 = knots[i + 1];
|
|
4117
|
-
const px1 = this._knotPixel(chart, target, p1);
|
|
4118
|
-
const px2 = this._knotPixel(chart, target, p2);
|
|
4119
|
-
if (!px1 || !px2) continue;
|
|
4120
|
-
patches.push({
|
|
4121
|
-
id: `trend_line_${key}_${seg.id}_${i}`,
|
|
4122
|
-
shape: { x1: px1[0], y1: px1[1], x2: px2[0], y2: px2[1] }
|
|
4123
|
-
});
|
|
4124
|
-
if (canMirror) {
|
|
4125
|
-
const mx1 = this._knotPixel(chart, target, p1, "mirror");
|
|
4126
|
-
const mx2 = this._knotPixel(chart, target, p2, "mirror");
|
|
4127
|
-
if (mx1 && mx2) {
|
|
4128
|
-
patches.push({
|
|
4129
|
-
id: `trend_mirror_${key}_${seg.id}_${i}`,
|
|
4130
|
-
shape: { x1: mx1[0], y1: mx1[1], x2: mx2[0], y2: mx2[1] }
|
|
4131
|
-
});
|
|
4132
|
-
}
|
|
4133
|
-
}
|
|
4134
|
-
}
|
|
4135
|
-
knots.forEach((knot, i) => {
|
|
4136
|
-
const px = this._knotPixel(chart, target, knot);
|
|
4137
|
-
if (px) {
|
|
4138
|
-
patches.push({
|
|
4139
|
-
id: `trend_point_${key}_${seg.id}_${i}`,
|
|
4140
|
-
shape: { cx: px[0], cy: px[1], r: 4 }
|
|
4141
|
-
});
|
|
4142
|
-
}
|
|
4143
|
-
if (canMirror) {
|
|
4144
|
-
const mx = this._knotPixel(chart, target, knot, "mirror");
|
|
4145
|
-
if (mx) {
|
|
4146
|
-
patches.push({
|
|
4147
|
-
id: `trend_mirror_point_${key}_${seg.id}_${i}`,
|
|
4148
|
-
shape: { cx: mx[0], cy: mx[1], r: 4 }
|
|
4149
|
-
});
|
|
4150
|
-
}
|
|
4151
|
-
}
|
|
4152
|
-
});
|
|
4153
|
-
});
|
|
4154
|
-
return patches;
|
|
4156
|
+
endPanFollow() {
|
|
4155
4157
|
}
|
|
4156
|
-
|
|
4157
|
-
if (chart && this._zrElCache) this._zrElCache.delete(chart);
|
|
4158
|
+
endFollowView() {
|
|
4158
4159
|
}
|
|
4159
|
-
|
|
4160
|
-
const zr = chart.getZr();
|
|
4161
|
-
if (!zr || !zr.storage || typeof zr.storage.traverse !== "function") return;
|
|
4162
|
-
zr.storage.traverse((el) => {
|
|
4163
|
-
const elId = el.id ?? el.anid ?? el.name ?? el.__ecGraphicId;
|
|
4164
|
-
if (elId == null) return;
|
|
4165
|
-
map.set(String(elId), el);
|
|
4166
|
-
});
|
|
4160
|
+
_patchAllPositions() {
|
|
4167
4161
|
}
|
|
4168
|
-
|
|
4169
|
-
if (!
|
|
4170
|
-
|
|
4171
|
-
if (
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
const
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4162
|
+
_isTrendSeriesOpt(series) {
|
|
4163
|
+
if (!series) return false;
|
|
4164
|
+
const name = Array.isArray(series.name) ? series.name[0] : series.name;
|
|
4165
|
+
if (name === "trend") return true;
|
|
4166
|
+
const id = String(series.id || "");
|
|
4167
|
+
return id.indexOf("trend_") === 0;
|
|
4168
|
+
}
|
|
4169
|
+
_findCurveSeriesInOption(option, paramId) {
|
|
4170
|
+
const list = option && option.series || [];
|
|
4171
|
+
for (let i = 0; i < list.length; i++) {
|
|
4172
|
+
const s = list[i];
|
|
4173
|
+
if (!s || this._isTrendSeriesOpt(s)) continue;
|
|
4174
|
+
const type = Array.isArray(s.type) ? s.type[0] : s.type;
|
|
4175
|
+
if (type && type !== "line") continue;
|
|
4176
|
+
const name = Array.isArray(s.name) ? s.name[0] : s.name;
|
|
4177
|
+
if (name === "helper" || name === "log-grid" || name === "推荐值") continue;
|
|
4178
|
+
if (String(s.paramId) === String(paramId)) return s;
|
|
4183
4179
|
}
|
|
4184
4180
|
return null;
|
|
4185
4181
|
}
|
|
4186
|
-
|
|
4187
|
-
const
|
|
4188
|
-
|
|
4189
|
-
|
|
4182
|
+
_firstKnotDepth(target) {
|
|
4183
|
+
const segs = target && target.segments || [];
|
|
4184
|
+
for (let i = 0; i < segs.length; i++) {
|
|
4185
|
+
const knot = (segs[i].knots || [])[0];
|
|
4186
|
+
if (knot && Number.isFinite(Number(knot.depth))) return Number(knot.depth);
|
|
4187
|
+
}
|
|
4188
|
+
return 0;
|
|
4190
4189
|
}
|
|
4191
|
-
|
|
4192
|
-
const
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
const clickX = Math.max(range.valueMin, Math.min(range.valueMax, data.value));
|
|
4198
|
-
const all = this._allKnots(target.key);
|
|
4199
|
-
const idx = all.indexOf(knot);
|
|
4200
|
-
if (idx > 0) depth = Math.max(depth, all[idx - 1].depth);
|
|
4201
|
-
if (idx >= 0 && idx < all.length - 1) depth = Math.min(depth, all[idx + 1].depth);
|
|
4202
|
-
knot.depth = parseFloat(depth.toFixed(3));
|
|
4203
|
-
this._applyPointerValue(chart, target, knot, knot.depth, clickX, role);
|
|
4204
|
-
return true;
|
|
4190
|
+
_curveAxisOf(chart, target) {
|
|
4191
|
+
const info = findSeriesForDepth(chart, target.paramId, this._firstKnotDepth(target));
|
|
4192
|
+
return {
|
|
4193
|
+
xAxisIndex: info && info.xAxisIndex != null ? info.xAxisIndex : 0,
|
|
4194
|
+
yAxisIndex: info && info.yAxisIndex != null ? info.yAxisIndex : 0
|
|
4195
|
+
};
|
|
4205
4196
|
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4197
|
+
_buildOneTrendSeries(id, data, lineStyle, pointStyle, xAxisIndex, yAxisIndex) {
|
|
4198
|
+
return {
|
|
4199
|
+
id,
|
|
4200
|
+
name: "trend",
|
|
4201
|
+
type: "line",
|
|
4202
|
+
data,
|
|
4203
|
+
xAxisIndex,
|
|
4204
|
+
yAxisIndex,
|
|
4205
|
+
clip: true,
|
|
4206
|
+
animation: false,
|
|
4207
|
+
silent: true,
|
|
4208
|
+
large: false,
|
|
4209
|
+
z: TREND_LINE_Z,
|
|
4210
|
+
zlevel: 0,
|
|
4211
|
+
symbol: "circle",
|
|
4212
|
+
symbolSize: 8,
|
|
4213
|
+
showSymbol: true,
|
|
4214
|
+
hoverAnimation: false,
|
|
4215
|
+
legendHoverLink: false,
|
|
4216
|
+
connectNulls: false,
|
|
4217
|
+
tooltip: { show: false },
|
|
4218
|
+
emphasis: { disabled: true },
|
|
4219
|
+
lineStyle: {
|
|
4220
|
+
color: lineStyle.stroke,
|
|
4221
|
+
width: lineStyle.lineWidth,
|
|
4222
|
+
type: lineStyle.lineDash || "solid"
|
|
4223
|
+
},
|
|
4224
|
+
itemStyle: {
|
|
4225
|
+
color: pointStyle.fill,
|
|
4226
|
+
borderColor: pointStyle.stroke,
|
|
4227
|
+
borderWidth: pointStyle.lineWidth
|
|
4228
|
+
}
|
|
4229
|
+
};
|
|
4230
|
+
}
|
|
4231
|
+
_knotPoint(x, depth) {
|
|
4232
|
+
return { value: [x, depth], symbol: "circle", symbolSize: 8 };
|
|
4233
|
+
}
|
|
4234
|
+
_segSeriesData(knots, role) {
|
|
4235
|
+
const raw = [];
|
|
4236
|
+
for (let i = 0; i < (knots || []).length; i++) {
|
|
4237
|
+
const knot = knots[i];
|
|
4238
|
+
const x = this._knotDrawX(knot, role);
|
|
4239
|
+
const depth = Number(knot && knot.depth);
|
|
4240
|
+
if (x == null || !Number.isFinite(depth)) continue;
|
|
4241
|
+
raw.push([x, depth]);
|
|
4242
|
+
}
|
|
4243
|
+
if (raw.length < 2) {
|
|
4244
|
+
return raw.map((p) => this._knotPoint(p[0], p[1]));
|
|
4245
|
+
}
|
|
4246
|
+
const data = [];
|
|
4247
|
+
for (let i = 0; i < raw.length - 1; i++) {
|
|
4248
|
+
const a = raw[i];
|
|
4249
|
+
const b = raw[i + 1];
|
|
4250
|
+
data.push(this._knotPoint(a[0], a[1]));
|
|
4251
|
+
const span = Math.abs(b[1] - a[1]);
|
|
4252
|
+
const n = Math.min(160, Math.max(0, Math.floor(span / 4)));
|
|
4253
|
+
for (let k = 1; k < n; k++) {
|
|
4254
|
+
const t = k / n;
|
|
4255
|
+
data.push({
|
|
4256
|
+
value: [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t],
|
|
4257
|
+
symbol: "none"
|
|
4229
4258
|
});
|
|
4230
|
-
}
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4261
|
+
const last = raw[raw.length - 1];
|
|
4262
|
+
data.push(this._knotPoint(last[0], last[1]));
|
|
4263
|
+
return data;
|
|
4264
|
+
}
|
|
4265
|
+
/** 曲线仍 weakFilter;趋势线点太稀,滤掉窗外控制点后穿过视窗的线会断。8.25 */
|
|
4266
|
+
applyDataZoomSkipTrend(option) {
|
|
4267
|
+
if (!option) return;
|
|
4268
|
+
const raw = option.dataZoom;
|
|
4269
|
+
if (!raw) return;
|
|
4270
|
+
const list = Array.isArray(raw) ? raw : [raw];
|
|
4271
|
+
const indexes = [];
|
|
4272
|
+
const series = option.series || [];
|
|
4273
|
+
for (let i = 0; i < series.length; i++) {
|
|
4274
|
+
if (!this._isTrendSeriesOpt(series[i])) indexes.push(i);
|
|
4275
|
+
}
|
|
4276
|
+
if (!indexes.length) return;
|
|
4277
|
+
list.forEach((dz) => {
|
|
4278
|
+
if (dz) dz.seriesIndex = indexes;
|
|
4231
4279
|
});
|
|
4232
4280
|
}
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4281
|
+
dataZoomSeriesIndex(chart) {
|
|
4282
|
+
if (!chart || chart.isDisposed()) return null;
|
|
4283
|
+
try {
|
|
4284
|
+
const list = chart.getModel().getSeries() || [];
|
|
4285
|
+
const indexes = [];
|
|
4286
|
+
for (let i = 0; i < list.length; i++) {
|
|
4287
|
+
const sm = list[i];
|
|
4288
|
+
const opt = sm && sm.option || {};
|
|
4289
|
+
const name = Array.isArray(sm.name) ? sm.name[0] : sm.name;
|
|
4290
|
+
if (this._isTrendSeriesOpt({ name, id: opt.id })) continue;
|
|
4291
|
+
if (sm.seriesIndex != null) indexes.push(sm.seriesIndex);
|
|
4292
|
+
}
|
|
4293
|
+
return indexes.length ? indexes : null;
|
|
4294
|
+
} catch (e) {
|
|
4295
|
+
return null;
|
|
4243
4296
|
}
|
|
4244
|
-
const onDown = (e) => {
|
|
4245
|
-
this._clearClickTimer();
|
|
4246
|
-
this.activeKey = target.key;
|
|
4247
|
-
this.dragSession = { chart, target, knot, role, graphic: true };
|
|
4248
|
-
this._setPanLocked(true);
|
|
4249
|
-
if (e && typeof e.stop === "function") e.stop();
|
|
4250
|
-
if (e && e.event) {
|
|
4251
|
-
e.event.preventDefault();
|
|
4252
|
-
e.event.stopPropagation();
|
|
4253
|
-
}
|
|
4254
|
-
};
|
|
4255
|
-
const onDrag = () => {
|
|
4256
|
-
if (!this.dragSession) {
|
|
4257
|
-
this.dragSession = { chart, target, knot, role, graphic: true };
|
|
4258
|
-
this._setPanLocked(true);
|
|
4259
|
-
}
|
|
4260
|
-
const [x, y] = this._graphicPixel(el);
|
|
4261
|
-
if (!this._applyKnotPixel(chart, target, knot, role, x, y)) return;
|
|
4262
|
-
el.x = 0;
|
|
4263
|
-
el.y = 0;
|
|
4264
|
-
this._patchLanePositions(target.laneId);
|
|
4265
|
-
};
|
|
4266
|
-
const onEnd = () => {
|
|
4267
|
-
if (!this.dragSession) return;
|
|
4268
|
-
const sessionTarget = this.dragSession.target;
|
|
4269
|
-
this.dragSession = null;
|
|
4270
|
-
this._setPanLocked(false, true);
|
|
4271
|
-
this._ignoreClickUntil = Date.now() + 300;
|
|
4272
|
-
this._emitChange(sessionTarget, { redraw: false });
|
|
4273
|
-
};
|
|
4274
|
-
el.__trendOnDown = onDown;
|
|
4275
|
-
el.__trendOnDrag = onDrag;
|
|
4276
|
-
el.__trendOnEnd = onEnd;
|
|
4277
|
-
el.__trendDragBound = true;
|
|
4278
|
-
el.on("mousedown", onDown);
|
|
4279
|
-
el.on("drag", onDrag);
|
|
4280
|
-
el.on("dragend", onEnd);
|
|
4281
4297
|
}
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4298
|
+
/** 笛卡尔 [曲线值, 井深];对数道 X 已是 lg。和曲线共用轴,dataZoom 同一帧带走。8.25 */
|
|
4299
|
+
_buildTrendSeries(target, xAxisIndex, yAxisIndex) {
|
|
4300
|
+
const list = [];
|
|
4301
|
+
const { key, segments, line } = target;
|
|
4302
|
+
const canMirror = this._canMirror(line, segments);
|
|
4303
|
+
const doubleLine = this._useGammaStyle(line, segments);
|
|
4304
|
+
const mainLineStyle = doubleLine ? TREND_DOUBLE_LINE_STYLE : TREND_LINE_STYLE;
|
|
4305
|
+
const mainPointStyle = doubleLine ? TREND_DOUBLE_POINT_STYLE : TREND_POINT_STYLE;
|
|
4306
|
+
(segments || []).forEach((seg) => {
|
|
4307
|
+
const knots = seg.knots || [];
|
|
4308
|
+
if (!knots.length) return;
|
|
4309
|
+
list.push(
|
|
4310
|
+
this._buildOneTrendSeries(
|
|
4311
|
+
`trend_${key}_${seg.id}`,
|
|
4312
|
+
this._segSeriesData(knots, "main"),
|
|
4313
|
+
mainLineStyle,
|
|
4314
|
+
mainPointStyle,
|
|
4315
|
+
xAxisIndex,
|
|
4316
|
+
yAxisIndex
|
|
4317
|
+
)
|
|
4318
|
+
);
|
|
4319
|
+
if (!canMirror) return;
|
|
4320
|
+
const mirror = this._segSeriesData(knots, "mirror");
|
|
4321
|
+
if (!mirror.length) return;
|
|
4322
|
+
list.push(
|
|
4323
|
+
this._buildOneTrendSeries(
|
|
4324
|
+
`trend_mirror_${key}_${seg.id}`,
|
|
4325
|
+
mirror,
|
|
4326
|
+
TREND_MIRROR_LINE_STYLE,
|
|
4327
|
+
TREND_MIRROR_POINT_STYLE,
|
|
4328
|
+
xAxisIndex,
|
|
4329
|
+
yAxisIndex
|
|
4330
|
+
)
|
|
4331
|
+
);
|
|
4290
4332
|
});
|
|
4291
|
-
|
|
4292
|
-
if (applied > 0 && zr && typeof zr.refresh === "function") zr.refresh();
|
|
4293
|
-
return applied > 0;
|
|
4333
|
+
return list;
|
|
4294
4334
|
}
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
if (!
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4335
|
+
/** 刷 option 时给该道补上趋势 series,所有有控制点的泳道都会走。8.25 */
|
|
4336
|
+
appendSeriesToOption(option, lane) {
|
|
4337
|
+
if (!option || !lane) return option;
|
|
4338
|
+
if (!Array.isArray(option.series)) option.series = [];
|
|
4339
|
+
option.series = option.series.filter((s) => !this._isTrendSeriesOpt(s));
|
|
4340
|
+
const targets = this.listDrawableTargets().filter((t) => t.laneId === lane.laneId);
|
|
4341
|
+
const added = [];
|
|
4342
|
+
targets.forEach((target) => {
|
|
4343
|
+
const curve = this._findCurveSeriesInOption(option, target.paramId);
|
|
4344
|
+
if (!curve) return;
|
|
4345
|
+
const xAxisIndex = curve.xAxisIndex == null ? 0 : Number(curve.xAxisIndex);
|
|
4346
|
+
const yAxisIndex = curve.yAxisIndex == null ? 0 : Number(curve.yAxisIndex);
|
|
4347
|
+
added.push(...this._buildTrendSeries(target, xAxisIndex, yAxisIndex));
|
|
4348
|
+
});
|
|
4349
|
+
option.series.push(...added);
|
|
4350
|
+
this._seriesIds[lane.laneId] = added.map((s) => s.id);
|
|
4351
|
+
this.applyDataZoomSkipTrend(option);
|
|
4352
|
+
return option;
|
|
4305
4353
|
}
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
},
|
|
4314
|
-
{ silent: true, lazyUpdate: false }
|
|
4315
|
-
);
|
|
4354
|
+
_clearLeftoverGraphic(chart) {
|
|
4355
|
+
if (!chart || chart.isDisposed() || this._graphicCleared.has(chart)) return;
|
|
4356
|
+
this._graphicCleared.add(chart);
|
|
4357
|
+
try {
|
|
4358
|
+
chart.setOption({ graphic: [] }, { replaceMerge: ["graphic"], silent: true, lazyUpdate: false });
|
|
4359
|
+
} catch (e) {
|
|
4360
|
+
}
|
|
4316
4361
|
}
|
|
4317
4362
|
renderAll(forceReplace = false) {
|
|
4318
4363
|
const lanes = this.host.currentTemplate && this.host.currentTemplate.lanes || [];
|
|
4319
4364
|
lanes.forEach((lane) => this.renderLane(lane.laneId, forceReplace));
|
|
4320
4365
|
}
|
|
4321
|
-
/**
|
|
4366
|
+
/** 用笛卡尔 series 画趋势线;平移/缩放交给 dataZoom,不跟像素。8.25 */
|
|
4322
4367
|
renderLane(laneId, forceReplace = false) {
|
|
4368
|
+
if (!this._alive()) return;
|
|
4323
4369
|
const chart = this.getChart(laneId);
|
|
4324
4370
|
if (!chart) return;
|
|
4371
|
+
this._clearLeftoverGraphic(chart);
|
|
4325
4372
|
const targets = this.listDrawableTargets().filter((t) => t.laneId === laneId);
|
|
4326
|
-
const
|
|
4373
|
+
const next = [];
|
|
4327
4374
|
targets.forEach((target) => {
|
|
4328
|
-
|
|
4375
|
+
const axis = this._curveAxisOf(chart, target);
|
|
4376
|
+
next.push(...this._buildTrendSeries(target, axis.xAxisIndex, axis.yAxisIndex));
|
|
4329
4377
|
});
|
|
4330
|
-
const
|
|
4331
|
-
if (hasKnots && !elements.length) return;
|
|
4332
|
-
const nextIds = elements.map((el) => el.id);
|
|
4333
|
-
const prevIds = this._graphicIds[laneId] || [];
|
|
4334
|
-
const prevSet = new Set(prevIds);
|
|
4378
|
+
const nextIds = next.map((s) => s.id);
|
|
4335
4379
|
const nextSet = new Set(nextIds);
|
|
4336
|
-
const
|
|
4337
|
-
const
|
|
4338
|
-
const
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4380
|
+
const liveIds = this._chartTrendSeriesIds(chart);
|
|
4381
|
+
const prevIds = [.../* @__PURE__ */ new Set([...this._seriesIds[laneId] || [], ...liveIds])];
|
|
4382
|
+
const replace = !!(forceReplace && !this.dragSession);
|
|
4383
|
+
const patch = next.map((s) => ({
|
|
4384
|
+
...s,
|
|
4385
|
+
data: s.data || [],
|
|
4386
|
+
$action: replace ? "replace" : "merge"
|
|
4387
|
+
}));
|
|
4388
|
+
prevIds.forEach((id) => {
|
|
4389
|
+
if (!nextSet.has(id)) patch.push({ id, $action: "remove" });
|
|
4390
|
+
});
|
|
4391
|
+
if (patch.length) {
|
|
4392
|
+
try {
|
|
4393
|
+
chart.setOption({ series: patch }, { silent: true, lazyUpdate: false });
|
|
4394
|
+
} catch (e) {
|
|
4348
4395
|
}
|
|
4349
|
-
if (removedIds.length) this._removeGraphicIds(chart, removedIds);
|
|
4350
|
-
if (added.length) this._addGraphicElements(chart, added);
|
|
4351
4396
|
}
|
|
4352
|
-
this.
|
|
4353
|
-
this.
|
|
4354
|
-
this.
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
const
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
elements.push({
|
|
4372
|
-
type: "line",
|
|
4373
|
-
id: `trend_line_${key}_${seg.id}_${i}`,
|
|
4374
|
-
shape: { x1: px1[0], y1: px1[1], x2: px2[0], y2: px2[1] },
|
|
4375
|
-
style: { ...mainLineStyle },
|
|
4376
|
-
z: TREND_LINE_Z,
|
|
4377
|
-
silent: true
|
|
4378
|
-
});
|
|
4379
|
-
if (canMirror) {
|
|
4380
|
-
const mx1 = this._knotPixel(chart, target, p1, "mirror");
|
|
4381
|
-
const mx2 = this._knotPixel(chart, target, p2, "mirror");
|
|
4382
|
-
if (mx1 && mx2) {
|
|
4383
|
-
elements.push({
|
|
4384
|
-
type: "line",
|
|
4385
|
-
id: `trend_mirror_${key}_${seg.id}_${i}`,
|
|
4386
|
-
shape: { x1: mx1[0], y1: mx1[1], x2: mx2[0], y2: mx2[1] },
|
|
4387
|
-
style: { ...TREND_MIRROR_LINE_STYLE },
|
|
4388
|
-
z: TREND_LINE_Z - 1,
|
|
4389
|
-
silent: true
|
|
4390
|
-
});
|
|
4397
|
+
this._seriesIds[laneId] = nextIds;
|
|
4398
|
+
if (!this.dragSession) this._syncCachedOption(laneId);
|
|
4399
|
+
if (this.dragSession) {
|
|
4400
|
+
this.updateCursor(laneId);
|
|
4401
|
+
return;
|
|
4402
|
+
}
|
|
4403
|
+
const idsChanged = nextIds.length !== prevIds.length || nextIds.some((id, i) => id !== prevIds[i]);
|
|
4404
|
+
if (idsChanged) {
|
|
4405
|
+
const skip = this.dataZoomSeriesIndex(chart);
|
|
4406
|
+
if (skip && skip.length) {
|
|
4407
|
+
try {
|
|
4408
|
+
const dz = chart.getModel().getComponent("dataZoom", 0);
|
|
4409
|
+
const opt = dz && dz.option;
|
|
4410
|
+
const next2 = { seriesIndex: skip };
|
|
4411
|
+
if (opt) {
|
|
4412
|
+
if (opt.start != null) next2.start = opt.start;
|
|
4413
|
+
if (opt.end != null) next2.end = opt.end;
|
|
4414
|
+
if (opt.startValue != null) next2.startValue = opt.startValue;
|
|
4415
|
+
if (opt.endValue != null) next2.endValue = opt.endValue;
|
|
4391
4416
|
}
|
|
4417
|
+
chart.setOption({ dataZoom: [next2] }, { silent: true, lazyUpdate: true });
|
|
4418
|
+
} catch (e) {
|
|
4392
4419
|
}
|
|
4393
4420
|
}
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4421
|
+
}
|
|
4422
|
+
this.updateCursor(laneId);
|
|
4423
|
+
}
|
|
4424
|
+
/** 把当前 store 写回 allOptions,避免随后 notMerge 用旧趋势 series 把点盖回去。8.25 */
|
|
4425
|
+
_syncCachedOption(laneId) {
|
|
4426
|
+
const host = this.host;
|
|
4427
|
+
if (!host || typeof host.getOptionsByLineId !== "function") return null;
|
|
4428
|
+
const option = host.getOptionsByLineId(laneId);
|
|
4429
|
+
if (!option || !Array.isArray(option.series)) return null;
|
|
4430
|
+
const lanes = host.currentTemplate && host.currentTemplate.lanes || [];
|
|
4431
|
+
const lane = lanes.find((l) => l.laneId === laneId);
|
|
4432
|
+
if (!lane) return null;
|
|
4433
|
+
this.appendSeriesToOption(option, lane);
|
|
4434
|
+
return option;
|
|
4435
|
+
}
|
|
4436
|
+
/** 删点后走整份 option 替换,ECharts 才会丢掉缩短后的旧 data。8.25 */
|
|
4437
|
+
_flushLane(laneId) {
|
|
4438
|
+
const option = this._syncCachedOption(laneId);
|
|
4439
|
+
if (option && this.host && typeof this.host.flushLaneChartOption === "function") {
|
|
4440
|
+
option.__kdTrendSynced = true;
|
|
4441
|
+
try {
|
|
4442
|
+
this.host.flushLaneChartOption(laneId, option);
|
|
4443
|
+
} finally {
|
|
4444
|
+
delete option.__kdTrendSynced;
|
|
4445
|
+
}
|
|
4446
|
+
this.updateCursor(laneId);
|
|
4447
|
+
return;
|
|
4448
|
+
}
|
|
4449
|
+
this.renderLane(laneId, true);
|
|
4450
|
+
}
|
|
4451
|
+
_chartTrendSeriesIds(chart) {
|
|
4452
|
+
if (!chart || chart.isDisposed()) return [];
|
|
4453
|
+
try {
|
|
4454
|
+
const list = chart.getModel().getSeries() || [];
|
|
4455
|
+
const ids = [];
|
|
4456
|
+
for (let i = 0; i < list.length; i++) {
|
|
4457
|
+
const sm = list[i];
|
|
4458
|
+
const opt = sm && sm.option || {};
|
|
4459
|
+
const name = Array.isArray(sm.name) ? sm.name[0] : sm.name;
|
|
4460
|
+
const id = opt.id || sm.id;
|
|
4461
|
+
if (this._isTrendSeriesOpt({ name, id }) && id) ids.push(id);
|
|
4462
|
+
}
|
|
4463
|
+
return ids;
|
|
4464
|
+
} catch (e) {
|
|
4465
|
+
return [];
|
|
4466
|
+
}
|
|
4427
4467
|
}
|
|
4428
4468
|
_findKnotAtPointer(chart, target, offsetX, offsetY, radius = TREND_HIT_RADIUS) {
|
|
4429
4469
|
let best = null;
|
|
4430
4470
|
let bestDist = radius;
|
|
4431
4471
|
const canMirror = this._canMirror(target.line, target.segments);
|
|
4432
4472
|
for (const seg of target.segments || []) {
|
|
4433
|
-
|
|
4473
|
+
const knots = seg.knots || [];
|
|
4474
|
+
for (let i = 0; i < knots.length; i++) {
|
|
4475
|
+
const knot = knots[i];
|
|
4434
4476
|
const px = this._knotPixel(chart, target, knot);
|
|
4435
4477
|
if (px) {
|
|
4436
4478
|
const dist = Math.hypot(px[0] - offsetX, px[1] - offsetY);
|
|
4437
4479
|
if (dist <= bestDist) {
|
|
4438
|
-
best = { knot, seg, role: "main" };
|
|
4480
|
+
best = { knot, seg, knotIndex: i, role: "main" };
|
|
4439
4481
|
bestDist = dist;
|
|
4440
4482
|
}
|
|
4441
4483
|
}
|
|
@@ -4444,7 +4486,7 @@ class TrendLineManager {
|
|
|
4444
4486
|
if (!mx) continue;
|
|
4445
4487
|
const mirrorDist = Math.hypot(mx[0] - offsetX, mx[1] - offsetY);
|
|
4446
4488
|
if (mirrorDist <= bestDist) {
|
|
4447
|
-
best = { knot, seg, role: "mirror" };
|
|
4489
|
+
best = { knot, seg, knotIndex: i, role: "mirror" };
|
|
4448
4490
|
bestDist = mirrorDist;
|
|
4449
4491
|
}
|
|
4450
4492
|
}
|
|
@@ -4453,6 +4495,11 @@ class TrendLineManager {
|
|
|
4453
4495
|
}
|
|
4454
4496
|
/** 单击空白处加点;延迟执行以便和双击断段区分。命中已有点则不加点。返回 true 表示已消费本次点击。8.21 */
|
|
4455
4497
|
handleClick(e, laneId) {
|
|
4498
|
+
if (!this._alive()) return false;
|
|
4499
|
+
if (this.dragSession) {
|
|
4500
|
+
this._endDrag(true);
|
|
4501
|
+
return true;
|
|
4502
|
+
}
|
|
4456
4503
|
const target = this.getTargetByLane(laneId);
|
|
4457
4504
|
if (!target || !target.editable) return false;
|
|
4458
4505
|
if (Date.now() < this._ignoreClickUntil) return true;
|
|
@@ -4465,6 +4512,7 @@ class TrendLineManager {
|
|
|
4465
4512
|
this._clearClickTimer();
|
|
4466
4513
|
this.clickTimer = setTimeout(() => {
|
|
4467
4514
|
this.clickTimer = null;
|
|
4515
|
+
if (!this._alive()) return;
|
|
4468
4516
|
this._addPoint(chart, target, offsetX, offsetY);
|
|
4469
4517
|
}, TREND_CLICK_DELAY_MS);
|
|
4470
4518
|
return true;
|
|
@@ -4486,7 +4534,7 @@ class TrendLineManager {
|
|
|
4486
4534
|
}
|
|
4487
4535
|
return true;
|
|
4488
4536
|
}
|
|
4489
|
-
/**
|
|
4537
|
+
/** 右键命中控制点时弹出「删除控制点」。打开菜单时不要 setOption,否则会吞掉菜单点击。8.21 */
|
|
4490
4538
|
handleContextMenu(e, laneId) {
|
|
4491
4539
|
const target = this.getTargetByLane(laneId);
|
|
4492
4540
|
if (!target || !target.editable) return false;
|
|
@@ -4500,14 +4548,23 @@ class TrendLineManager {
|
|
|
4500
4548
|
this.host.showTrendKnotContextMenu(e, {
|
|
4501
4549
|
key: target.key,
|
|
4502
4550
|
knot: hit.knot,
|
|
4551
|
+
segId: hit.seg && hit.seg.id,
|
|
4552
|
+
knotIndex: hit.knotIndex,
|
|
4553
|
+
depth: hit.knot.depth,
|
|
4554
|
+
value: hit.knot.value,
|
|
4555
|
+
plotValue: hit.knot.plotValue,
|
|
4503
4556
|
laneId
|
|
4504
4557
|
});
|
|
4505
|
-
this.renderLane(laneId);
|
|
4506
4558
|
return true;
|
|
4507
4559
|
}
|
|
4508
4560
|
/** 指针靠近控制点时先停地应力平移,按下时才来得及拖点。8.22 */
|
|
4509
4561
|
onZrHover(e, laneId) {
|
|
4510
|
-
if (this.
|
|
4562
|
+
if (!this._alive()) return;
|
|
4563
|
+
if (this.dragSession) {
|
|
4564
|
+
e.__ecRoamConsumed = true;
|
|
4565
|
+
if (typeof e.stop === "function") e.stop();
|
|
4566
|
+
return;
|
|
4567
|
+
}
|
|
4511
4568
|
if (this.host && typeof this.host.isChartBusy === "function" && this.host.isChartBusy()) {
|
|
4512
4569
|
return;
|
|
4513
4570
|
}
|
|
@@ -4530,38 +4587,32 @@ class TrendLineManager {
|
|
|
4530
4587
|
this.host.setInsideDataZoomPanEnabled(!locked);
|
|
4531
4588
|
}
|
|
4532
4589
|
}
|
|
4533
|
-
/** zr
|
|
4590
|
+
/** 左键拖点与右键删点同一套命中(zr offset + _findKnotAtPointer)。8.25 */
|
|
4534
4591
|
onZrMouseDown(e, laneId) {
|
|
4592
|
+
if (!this._alive()) return;
|
|
4535
4593
|
if (e.which != null && e.which !== 1 && e.event && e.event.button !== 0) return;
|
|
4594
|
+
if (this.dragSession) {
|
|
4595
|
+
e.__ecRoamConsumed = true;
|
|
4596
|
+
if (typeof e.stop === "function") e.stop();
|
|
4597
|
+
this._endDrag(true);
|
|
4598
|
+
return;
|
|
4599
|
+
}
|
|
4536
4600
|
const target = this.getTargetByLane(laneId);
|
|
4537
4601
|
const chart = this.getChart(laneId);
|
|
4538
|
-
if (!target || !target.editable || !chart
|
|
4602
|
+
if (!target || !target.editable || !chart) return;
|
|
4539
4603
|
const { offsetX, offsetY } = eventOffsetInChart(chart, e);
|
|
4540
|
-
|
|
4604
|
+
const hit = this._findKnotAtPointer(chart, target, offsetX, offsetY);
|
|
4605
|
+
if (!hit) return;
|
|
4606
|
+
e.__ecRoamConsumed = true;
|
|
4541
4607
|
if (typeof e.stop === "function") e.stop();
|
|
4542
4608
|
e.cancelBubble = true;
|
|
4543
4609
|
if (e.event) {
|
|
4544
4610
|
e.event.preventDefault();
|
|
4545
4611
|
e.event.stopPropagation();
|
|
4546
4612
|
}
|
|
4547
|
-
}
|
|
4548
|
-
/** 仅左键拖拽控制点。右键 mousedown 会先于 contextmenu,绝不能当拖拽处理。8.21 */
|
|
4549
|
-
onMouseDown(nativeEvent, laneId) {
|
|
4550
|
-
if (nativeEvent.button !== 0) return;
|
|
4551
|
-
const target = this.getTargetByLane(laneId);
|
|
4552
|
-
if (!target || !target.editable || this.dragSession) return;
|
|
4553
|
-
const chart = this.getChart(laneId);
|
|
4554
|
-
if (!chart) return;
|
|
4555
|
-
const { offsetX, offsetY } = eventOffsetInChart(chart, nativeEvent);
|
|
4556
|
-
const hit = this._findKnotAtPointer(chart, target, offsetX, offsetY);
|
|
4557
|
-
if (!hit) return;
|
|
4558
|
-
nativeEvent.stopPropagation();
|
|
4559
|
-
nativeEvent.stopImmediatePropagation();
|
|
4560
|
-
nativeEvent.preventDefault();
|
|
4561
4613
|
this._clearClickTimer();
|
|
4562
4614
|
this.activeKey = target.key;
|
|
4563
|
-
this.
|
|
4564
|
-
this._startDrag(chart, target, hit.knot, nativeEvent, hit.role);
|
|
4615
|
+
this._startDrag(chart, target, hit.knot, e, hit.role);
|
|
4565
4616
|
}
|
|
4566
4617
|
/** 沿深度增大方向追加控制点;曲线值限制在该线 min/max 内。8.21 */
|
|
4567
4618
|
_addPoint(chart, target, offsetX, offsetY) {
|
|
@@ -4657,6 +4708,7 @@ class TrendLineManager {
|
|
|
4657
4708
|
}
|
|
4658
4709
|
/** 清空全部趋势线控制点并重绘。8.22 */
|
|
4659
4710
|
resetAllTrendLines() {
|
|
4711
|
+
if (this.dragSession) this._endDrag(false);
|
|
4660
4712
|
const prev = this.listDrawableTargets().filter(
|
|
4661
4713
|
(t) => (t.segments || []).some((s) => (s.knots || []).length)
|
|
4662
4714
|
);
|
|
@@ -4670,25 +4722,39 @@ class TrendLineManager {
|
|
|
4670
4722
|
segments: []
|
|
4671
4723
|
});
|
|
4672
4724
|
});
|
|
4673
|
-
this.
|
|
4725
|
+
this._flushTrendLanes(prev);
|
|
4674
4726
|
}
|
|
4675
4727
|
/** 清空指定曲线的控制点;不传 key 则清当前编辑曲线。8.21 */
|
|
4676
4728
|
resetTrendLine(key) {
|
|
4677
4729
|
const target = key ? this.listDrawableTargets().find((t) => t.key === key) : this.getActiveTarget() || this.listDrawableTargets().find((t) => t.editable);
|
|
4678
4730
|
if (!target) return;
|
|
4731
|
+
if (this.dragSession) this._endDrag(false);
|
|
4679
4732
|
this.store[target.key] = { segments: [] };
|
|
4680
|
-
this.
|
|
4733
|
+
this._flushLane(target.laneId);
|
|
4681
4734
|
this._emitChange(target, { redraw: false });
|
|
4682
4735
|
}
|
|
4736
|
+
/** 把 store 已空的泳道整份 option 刷进图,线段才会从画面上消失。8.25 */
|
|
4737
|
+
_flushTrendLanes(prev) {
|
|
4738
|
+
const laneIds = /* @__PURE__ */ new Set();
|
|
4739
|
+
(prev || []).forEach((t) => t.laneId && laneIds.add(t.laneId));
|
|
4740
|
+
Object.keys(this._seriesIds).forEach((id) => laneIds.add(id));
|
|
4741
|
+
this.binds.forEach((_, laneId) => {
|
|
4742
|
+
const chart = this.getChart(laneId);
|
|
4743
|
+
if (chart && this._chartTrendSeriesIds(chart).length) laneIds.add(laneId);
|
|
4744
|
+
});
|
|
4745
|
+
if (!laneIds.size) {
|
|
4746
|
+
this.renderAll(true);
|
|
4747
|
+
return;
|
|
4748
|
+
}
|
|
4749
|
+
laneIds.forEach((laneId) => this._flushLane(laneId));
|
|
4750
|
+
}
|
|
4683
4751
|
/** 删除一个控制点。段内只剩 0~1 个点时整段丢掉(画不出线)。8.21 */
|
|
4684
4752
|
deleteKnot(payload) {
|
|
4685
|
-
if (!payload || !payload.key
|
|
4753
|
+
if (!payload || !payload.key) return;
|
|
4686
4754
|
const bucket = this.store[payload.key];
|
|
4687
4755
|
if (!bucket) return;
|
|
4688
4756
|
bucket.segments = bucket.segments.map((seg) => {
|
|
4689
|
-
const idx =
|
|
4690
|
-
(k) => k === payload.knot || Math.abs(k.depth - payload.knot.depth) < 0.05 && Math.abs(k.value - payload.knot.value) < 0.01
|
|
4691
|
-
);
|
|
4757
|
+
const idx = this._findKnotIndex(seg, payload);
|
|
4692
4758
|
if (idx < 0) return seg;
|
|
4693
4759
|
const knots = seg.knots.filter((_, i) => i !== idx);
|
|
4694
4760
|
if (knots.length <= 1) return { ...seg, knots: [] };
|
|
@@ -4696,9 +4762,32 @@ class TrendLineManager {
|
|
|
4696
4762
|
}).filter((s) => s.knots.length > 0);
|
|
4697
4763
|
const target = this.listDrawableTargets().find((t) => t.key === payload.key);
|
|
4698
4764
|
const laneId = target && target.laneId || payload.laneId;
|
|
4699
|
-
if (laneId) this.
|
|
4765
|
+
if (laneId) this._flushLane(laneId);
|
|
4700
4766
|
if (target) this._emitChange(target, { redraw: false });
|
|
4701
4767
|
}
|
|
4768
|
+
_findKnotIndex(seg, payload) {
|
|
4769
|
+
const knots = seg && seg.knots || [];
|
|
4770
|
+
if (!knots.length || !payload) return -1;
|
|
4771
|
+
if (payload.knot) {
|
|
4772
|
+
const byRef = knots.indexOf(payload.knot);
|
|
4773
|
+
if (byRef >= 0) return byRef;
|
|
4774
|
+
}
|
|
4775
|
+
if (payload.segId && seg.id !== payload.segId) return -1;
|
|
4776
|
+
if (Number.isInteger(payload.knotIndex) && payload.knotIndex >= 0 && payload.knotIndex < knots.length) {
|
|
4777
|
+
return payload.knotIndex;
|
|
4778
|
+
}
|
|
4779
|
+
const depth = payload.knot != null ? payload.knot.depth : payload.depth;
|
|
4780
|
+
const value = payload.knot != null ? payload.knot.value : payload.value;
|
|
4781
|
+
const plotValue = payload.knot != null ? payload.knot.plotValue : payload.plotValue;
|
|
4782
|
+
return knots.findIndex((k) => {
|
|
4783
|
+
if (depth == null || Math.abs(Number(k.depth) - Number(depth)) >= 0.05) return false;
|
|
4784
|
+
if (value != null && Math.abs(Number(k.value) - Number(value)) < 0.01) return true;
|
|
4785
|
+
if (plotValue != null && k.plotValue != null && Math.abs(Number(k.plotValue) - Number(plotValue)) < 0.01) {
|
|
4786
|
+
return true;
|
|
4787
|
+
}
|
|
4788
|
+
return value == null;
|
|
4789
|
+
});
|
|
4790
|
+
}
|
|
4702
4791
|
/** 返回 geosteering trendLinePoint 格式的线段数组;8137 带上 isDouble / calcType。8.22 */
|
|
4703
4792
|
getTrendLineData(mainId = "demo") {
|
|
4704
4793
|
const grouped = {};
|
|
@@ -4722,12 +4811,14 @@ class TrendLineManager {
|
|
|
4722
4811
|
}
|
|
4723
4812
|
const segs = this._prepareEchoSegments(paramId, segments);
|
|
4724
4813
|
this.store[key] = { segments: segs };
|
|
4725
|
-
if (found.line) found.line.trendSegments = segs;
|
|
4726
4814
|
this.renderLane(found.laneId);
|
|
4727
4815
|
}
|
|
4728
4816
|
/** 把 geosteering 线段数组灌进对应曲线并画出叠加层。8.21 */
|
|
4729
4817
|
setTrendLineList(lineList, overwrite = true) {
|
|
4730
|
-
if (!Array.isArray(lineList) || !lineList.length)
|
|
4818
|
+
if (!Array.isArray(lineList) || !lineList.length) {
|
|
4819
|
+
this.resetAllTrendLines();
|
|
4820
|
+
return;
|
|
4821
|
+
}
|
|
4731
4822
|
const grouped = fromTrendLineSavePayload(lineList);
|
|
4732
4823
|
Object.entries(grouped).forEach(([paramId, segments]) => {
|
|
4733
4824
|
this.setTrendLineData(paramId, segments, overwrite);
|
|
@@ -4763,33 +4854,58 @@ class TrendLineManager {
|
|
|
4763
4854
|
const last = target.segments[target.segments.length - 1];
|
|
4764
4855
|
return !!(last && !last._closed && last.knots && last.knots.length);
|
|
4765
4856
|
}
|
|
4766
|
-
/**
|
|
4857
|
+
/** 拖拽开始:按下不刷图,避免 setOption 把这次按住掐掉。8.25 */
|
|
4767
4858
|
_startDrag(chart, target, knot, nativeEvent, role = "main") {
|
|
4859
|
+
this._unbindDragWindow();
|
|
4768
4860
|
const onMove = (ev) => this._onDragMove(ev);
|
|
4769
|
-
const onUp = () =>
|
|
4861
|
+
const onUp = (ev) => {
|
|
4862
|
+
if (ev && ev.button != null && ev.button !== 0) return;
|
|
4863
|
+
this._endDrag(true);
|
|
4864
|
+
};
|
|
4865
|
+
const startStamp = nativeEvent && nativeEvent.timeStamp;
|
|
4866
|
+
const onClickEnd = (ev) => {
|
|
4867
|
+
if (ev && ev.button != null && ev.button !== 0) return;
|
|
4868
|
+
if (startStamp != null && ev.timeStamp === startStamp) return;
|
|
4869
|
+
this._endDrag(true);
|
|
4870
|
+
};
|
|
4871
|
+
const { offsetX, offsetY } = eventOffsetInChart(chart, nativeEvent);
|
|
4872
|
+
const px = this._knotPixel(chart, target, knot, role);
|
|
4770
4873
|
this.dragSession = {
|
|
4771
4874
|
chart,
|
|
4772
4875
|
target,
|
|
4773
4876
|
knot,
|
|
4774
4877
|
role,
|
|
4775
4878
|
onMove,
|
|
4776
|
-
onUp
|
|
4879
|
+
onUp,
|
|
4880
|
+
onClickEnd,
|
|
4881
|
+
grabDX: px ? px[0] - offsetX : 0,
|
|
4882
|
+
grabDY: px ? px[1] - offsetY : 0
|
|
4777
4883
|
};
|
|
4778
|
-
if (this.host && typeof this.host.setInsideDataZoomPanEnabled === "function") {
|
|
4779
|
-
this.host.setInsideDataZoomPanEnabled(false);
|
|
4780
|
-
}
|
|
4781
4884
|
window.addEventListener("mousemove", onMove);
|
|
4782
4885
|
window.addEventListener("mouseup", onUp);
|
|
4886
|
+
window.addEventListener("mousedown", onClickEnd, true);
|
|
4783
4887
|
this.updateCursor(target.laneId);
|
|
4784
|
-
this._onDragMove(nativeEvent);
|
|
4785
4888
|
}
|
|
4786
|
-
|
|
4889
|
+
_unbindDragWindow() {
|
|
4890
|
+
const session = this.dragSession;
|
|
4891
|
+
if (!session) return;
|
|
4892
|
+
window.removeEventListener("mousemove", session.onMove);
|
|
4893
|
+
window.removeEventListener("mouseup", session.onUp);
|
|
4894
|
+
if (session.onClickEnd) {
|
|
4895
|
+
window.removeEventListener("mousedown", session.onClickEnd, true);
|
|
4896
|
+
}
|
|
4897
|
+
this.dragSession = null;
|
|
4898
|
+
}
|
|
4899
|
+
/** 拖拽时点跟着鼠标走;夹在相邻点之间,不能越过前后控制点。8.21 */
|
|
4787
4900
|
_onDragMove(nativeEvent) {
|
|
4901
|
+
if (!this._alive()) return;
|
|
4788
4902
|
const session = this.dragSession;
|
|
4789
4903
|
if (!session) return;
|
|
4790
4904
|
const { chart, target, knot, role } = session;
|
|
4791
|
-
const
|
|
4792
|
-
const
|
|
4905
|
+
const pos = eventOffsetInChart(chart, nativeEvent);
|
|
4906
|
+
const offsetX = pos.offsetX + (session.grabDX || 0);
|
|
4907
|
+
const offsetY = pos.offsetY + (session.grabDY || 0);
|
|
4908
|
+
const data = this._pixelToDragTrend(chart, target, offsetX, offsetY);
|
|
4793
4909
|
if (!data) return;
|
|
4794
4910
|
const range = this._drawValueRange(target, chart, data.depth);
|
|
4795
4911
|
let depth = snapDepthToEdge(data.depth, range.depthMin, range.depthMax, DEPTH_EDGE_SNAP);
|
|
@@ -4803,19 +4919,33 @@ class TrendLineManager {
|
|
|
4803
4919
|
this._applyPointerValue(chart, target, knot, knot.depth, clickX, role);
|
|
4804
4920
|
this.renderLane(target.laneId);
|
|
4805
4921
|
}
|
|
4922
|
+
/** 拖点用轴 scale 反算,和画点同一套,避免点落在鼠标旁边。8.25 */
|
|
4923
|
+
_pixelToDragTrend(chart, target, offsetX, offsetY) {
|
|
4924
|
+
const finder = findSeriesForDepth(chart, target.paramId, this._firstKnotDepth(target));
|
|
4925
|
+
const fromAxis = axisPairFromPixel(
|
|
4926
|
+
chart,
|
|
4927
|
+
finder.xAxisIndex,
|
|
4928
|
+
finder.yAxisIndex,
|
|
4929
|
+
offsetX,
|
|
4930
|
+
offsetY
|
|
4931
|
+
);
|
|
4932
|
+
if (fromAxis) return fromAxis;
|
|
4933
|
+
return this._pixelToTrend(chart, target, offsetX, offsetY, true);
|
|
4934
|
+
}
|
|
4806
4935
|
/** emit=false 只结束拖拽不抛事件(右键菜单用)。8.21 */
|
|
4807
4936
|
_endDrag(emit) {
|
|
4808
4937
|
const session = this.dragSession;
|
|
4809
4938
|
if (!session) return;
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
this.dragSession = null;
|
|
4939
|
+
this._unbindDragWindow();
|
|
4940
|
+
if (!this._alive()) return;
|
|
4813
4941
|
this._panLockedByHover = false;
|
|
4814
4942
|
if (this.host && typeof this.host.setInsideDataZoomPanEnabled === "function") {
|
|
4815
4943
|
this.host.setInsideDataZoomPanEnabled(true);
|
|
4816
4944
|
}
|
|
4817
4945
|
this._ignoreClickUntil = Date.now() + 300;
|
|
4818
4946
|
this.updateCursor(session.target.laneId);
|
|
4947
|
+
this.renderLane(session.target.laneId, true);
|
|
4948
|
+
this._syncCachedOption(session.target.laneId);
|
|
4819
4949
|
if (emit) this._emitChange(session.target, { redraw: false });
|
|
4820
4950
|
}
|
|
4821
4951
|
_clearClickTimer() {
|
|
@@ -4827,6 +4957,7 @@ class TrendLineManager {
|
|
|
4827
4957
|
/** 抛 trend-change(拖拽过程中不抛,只在松开时抛);不写回响应式模板。8.22 */
|
|
4828
4958
|
// redraw=false:本地已画过,避免再 scheduleRender 把线闪掉。8.24
|
|
4829
4959
|
_emitChange(target, { redraw = true } = {}) {
|
|
4960
|
+
if (!this._alive() || !target) return;
|
|
4830
4961
|
const segments = cloneSegments(this.store[target.key] && this.store[target.key].segments || []);
|
|
4831
4962
|
this.host.$emit("trend-change", {
|
|
4832
4963
|
paramId: target.paramId,
|
|
@@ -4838,8 +4969,12 @@ class TrendLineManager {
|
|
|
4838
4969
|
/** 等 Vue / 图表 setOption 完成后再画叠加层。8.22 */
|
|
4839
4970
|
// 只 nextTick 一次,不再叠 rAF 连刷。8.24
|
|
4840
4971
|
_scheduleRenderAfterVue() {
|
|
4841
|
-
if (this.
|
|
4842
|
-
|
|
4972
|
+
if (!this._alive()) return;
|
|
4973
|
+
if (typeof this.host.$nextTick === "function") {
|
|
4974
|
+
this.host.$nextTick(() => {
|
|
4975
|
+
if (!this._alive()) return;
|
|
4976
|
+
this.scheduleRender();
|
|
4977
|
+
});
|
|
4843
4978
|
} else {
|
|
4844
4979
|
this.scheduleRender();
|
|
4845
4980
|
}
|
|
@@ -4956,6 +5091,15 @@ class TrendLineManager {
|
|
|
4956
5091
|
return pixelToData(chart, target.paramId, offsetX, offsetY, loose);
|
|
4957
5092
|
}
|
|
4958
5093
|
_trendToPixel(chart, target, value, depth) {
|
|
5094
|
+
const finder = findSeriesForDepth(chart, target.paramId, depth);
|
|
5095
|
+
const live = axisPairToPixel(
|
|
5096
|
+
chart,
|
|
5097
|
+
finder.xAxisIndex,
|
|
5098
|
+
finder.yAxisIndex,
|
|
5099
|
+
value,
|
|
5100
|
+
depth
|
|
5101
|
+
);
|
|
5102
|
+
if (live) return live;
|
|
4959
5103
|
const lane = this._laneById(target.laneId);
|
|
4960
5104
|
if (isLaneLogScale(lane)) {
|
|
4961
5105
|
return logTrendDataToPixel(chart, target.paramId, value, depth);
|
|
@@ -5183,11 +5327,16 @@ const _sfc_main$6 = {
|
|
|
5183
5327
|
type: Boolean,
|
|
5184
5328
|
default: true
|
|
5185
5329
|
},
|
|
5186
|
-
// 当前选中的泳道ID
|
|
5330
|
+
// 当前选中的泳道ID(最后一次点选,兼容旧 emit)
|
|
5187
5331
|
activeLaneId: {
|
|
5188
5332
|
type: [String, Number],
|
|
5189
5333
|
default: null
|
|
5190
5334
|
},
|
|
5335
|
+
// 地应力可同时选中多道。8.25
|
|
5336
|
+
activeLaneIds: {
|
|
5337
|
+
type: Array,
|
|
5338
|
+
default: () => []
|
|
5339
|
+
},
|
|
5191
5340
|
// 是否为地应力模式(只有为 true 时才启用泳道选中功能)
|
|
5192
5341
|
isGeomechanical: {
|
|
5193
5342
|
type: Boolean,
|
|
@@ -5260,6 +5409,10 @@ const _sfc_main$6 = {
|
|
|
5260
5409
|
clearTimeout(this.resizeTimer);
|
|
5261
5410
|
this.resizeTimer = null;
|
|
5262
5411
|
}
|
|
5412
|
+
if (this._curveConfigCloseTimer) {
|
|
5413
|
+
clearTimeout(this._curveConfigCloseTimer);
|
|
5414
|
+
this._curveConfigCloseTimer = 0;
|
|
5415
|
+
}
|
|
5263
5416
|
if (this.resizeObserver) {
|
|
5264
5417
|
this.resizeObserver.disconnect();
|
|
5265
5418
|
this.resizeObserver = null;
|
|
@@ -5288,6 +5441,7 @@ const _sfc_main$6 = {
|
|
|
5288
5441
|
return;
|
|
5289
5442
|
}
|
|
5290
5443
|
this.$nextTick(() => {
|
|
5444
|
+
if (this._isUnmounted) return;
|
|
5291
5445
|
const containerRef = this.$refs.containerRef;
|
|
5292
5446
|
if (!containerRef) {
|
|
5293
5447
|
return;
|
|
@@ -5667,10 +5821,11 @@ const _sfc_main$6 = {
|
|
|
5667
5821
|
isLaneTrendDraw(lane) {
|
|
5668
5822
|
return !!(lane && (lane.lines || []).some((line) => isLineDrawable(line)));
|
|
5669
5823
|
},
|
|
5670
|
-
//
|
|
5824
|
+
// 获取泳道头部样式:地应力已选中的道都画红框。8.25
|
|
5671
5825
|
getLaneHeaderStyle(lane) {
|
|
5672
5826
|
const base = this.headerStyle;
|
|
5673
|
-
const
|
|
5827
|
+
const ids = this.activeLaneIds || [];
|
|
5828
|
+
const isActive = this.isGeomechanical ? !!(lane && ids.some((id) => id === lane.laneId)) : this.isLaneTrendDraw(lane);
|
|
5674
5829
|
if (!isActive) return base;
|
|
5675
5830
|
return {
|
|
5676
5831
|
...base,
|
|
@@ -5683,7 +5838,10 @@ const _sfc_main$6 = {
|
|
|
5683
5838
|
},
|
|
5684
5839
|
closeCurveConfigDialog() {
|
|
5685
5840
|
this.curveConfigClosing = true;
|
|
5686
|
-
|
|
5841
|
+
if (this._curveConfigCloseTimer) clearTimeout(this._curveConfigCloseTimer);
|
|
5842
|
+
this._curveConfigCloseTimer = setTimeout(() => {
|
|
5843
|
+
this._curveConfigCloseTimer = 0;
|
|
5844
|
+
if (this._isUnmounted) return;
|
|
5687
5845
|
this.curveConfigVisible = false;
|
|
5688
5846
|
this.curveConfigClosing = false;
|
|
5689
5847
|
}, 300);
|
|
@@ -6691,7 +6849,7 @@ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
6691
6849
|
}, 8, ["modelValue", "onClose"])
|
|
6692
6850
|
], 544);
|
|
6693
6851
|
}
|
|
6694
|
-
const KdLaneContainerComponent = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6], ["__scopeId", "data-v-
|
|
6852
|
+
const KdLaneContainerComponent = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6], ["__scopeId", "data-v-814fbe51"]]);
|
|
6695
6853
|
const SLIDER_GROUP_ID = "depthSliderGroup";
|
|
6696
6854
|
function pad2(n) {
|
|
6697
6855
|
return n < 10 ? "0" + n : "" + n;
|
|
@@ -9298,11 +9456,86 @@ const _sfc_main$3 = {
|
|
|
9298
9456
|
const model = this.chart.getModel();
|
|
9299
9457
|
const list = model.queryComponents({ mainType: "graphic" }) || [];
|
|
9300
9458
|
if (!list.length) return;
|
|
9301
|
-
const graphic = list.map((m) => m.option).filter((item) =>
|
|
9459
|
+
const graphic = list.map((m) => m.option).filter((item) => {
|
|
9460
|
+
if (!item || !(item.id || item.elements || item.type)) return false;
|
|
9461
|
+
const id = String(item.id || "");
|
|
9462
|
+
return id.indexOf("trend_") !== 0;
|
|
9463
|
+
});
|
|
9302
9464
|
if (graphic.length) options.graphic = graphic;
|
|
9303
9465
|
} catch (e) {
|
|
9304
9466
|
}
|
|
9305
9467
|
},
|
|
9468
|
+
// notMerge 时把笛卡尔趋势 series 带回去,避免先消失再画。8.25
|
|
9469
|
+
// 只拷绘制字段,禁止展开 model.option(会带上坐标系等内部引用,图表拆不掉)。8.25
|
|
9470
|
+
_copyTrendSeriesOption(opt, id) {
|
|
9471
|
+
if (!opt) return null;
|
|
9472
|
+
const ls = opt.lineStyle || {};
|
|
9473
|
+
const is = opt.itemStyle || {};
|
|
9474
|
+
return {
|
|
9475
|
+
id: opt.id || id,
|
|
9476
|
+
name: "trend",
|
|
9477
|
+
type: "line",
|
|
9478
|
+
data: Array.isArray(opt.data) ? opt.data.slice() : [],
|
|
9479
|
+
xAxisIndex: opt.xAxisIndex,
|
|
9480
|
+
yAxisIndex: opt.yAxisIndex,
|
|
9481
|
+
clip: opt.clip,
|
|
9482
|
+
animation: false,
|
|
9483
|
+
silent: true,
|
|
9484
|
+
large: false,
|
|
9485
|
+
z: opt.z,
|
|
9486
|
+
zlevel: 0,
|
|
9487
|
+
symbol: opt.symbol,
|
|
9488
|
+
symbolSize: opt.symbolSize,
|
|
9489
|
+
showSymbol: opt.showSymbol,
|
|
9490
|
+
hoverAnimation: false,
|
|
9491
|
+
legendHoverLink: false,
|
|
9492
|
+
connectNulls: false,
|
|
9493
|
+
tooltip: { show: false },
|
|
9494
|
+
emphasis: { disabled: true },
|
|
9495
|
+
lineStyle: {
|
|
9496
|
+
color: ls.color,
|
|
9497
|
+
width: ls.width,
|
|
9498
|
+
type: ls.type
|
|
9499
|
+
},
|
|
9500
|
+
itemStyle: {
|
|
9501
|
+
color: is.color,
|
|
9502
|
+
borderColor: is.borderColor,
|
|
9503
|
+
borderWidth: is.borderWidth
|
|
9504
|
+
}
|
|
9505
|
+
};
|
|
9506
|
+
},
|
|
9507
|
+
_preserveTrendSeries(options) {
|
|
9508
|
+
if (!options || !this.chart || this.chart.isDisposed()) return;
|
|
9509
|
+
if (options.__kdTrendSynced) return;
|
|
9510
|
+
const incoming = Array.isArray(options.series) ? options.series : [];
|
|
9511
|
+
const hasTrend = incoming.some((s) => {
|
|
9512
|
+
if (!s) return false;
|
|
9513
|
+
const name = Array.isArray(s.name) ? s.name[0] : s.name;
|
|
9514
|
+
if (name === "trend") return true;
|
|
9515
|
+
const id = String(s.id || "");
|
|
9516
|
+
return id.indexOf("trend_") === 0;
|
|
9517
|
+
});
|
|
9518
|
+
if (hasTrend) return;
|
|
9519
|
+
try {
|
|
9520
|
+
const list = this.chart.getModel().getSeries() || [];
|
|
9521
|
+
const trends = [];
|
|
9522
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9523
|
+
for (let i = 0; i < list.length; i++) {
|
|
9524
|
+
const sm = list[i];
|
|
9525
|
+
const opt = sm && sm.option || {};
|
|
9526
|
+
const name = Array.isArray(sm.name) ? sm.name[0] : sm.name;
|
|
9527
|
+
const id = String(opt.id || sm.id || "");
|
|
9528
|
+
if (name !== "trend" && id.indexOf("trend_") !== 0) continue;
|
|
9529
|
+
if (!id || seen.has(id)) continue;
|
|
9530
|
+
seen.add(id);
|
|
9531
|
+
const copied = this._copyTrendSeriesOption(opt, id);
|
|
9532
|
+
if (copied) trends.push(copied);
|
|
9533
|
+
}
|
|
9534
|
+
if (!trends.length) return;
|
|
9535
|
+
options.series = incoming.concat(trends);
|
|
9536
|
+
} catch (e) {
|
|
9537
|
+
}
|
|
9538
|
+
},
|
|
9306
9539
|
// dataZoom 写进即将下发的 option,不再二次 setOption 打断 Chrome 平移。8.24
|
|
9307
9540
|
_applySavedDataZoomToOptions(options, savedState) {
|
|
9308
9541
|
if (!savedState || !options) return;
|
|
@@ -9352,6 +9585,7 @@ const _sfc_main$3 = {
|
|
|
9352
9585
|
const next = this.getOptionsWithTheme(options, skipClone);
|
|
9353
9586
|
this._applySavedDataZoomToOptions(next, savedDataZoom);
|
|
9354
9587
|
this._preserveGraphic(next);
|
|
9588
|
+
this._preserveTrendSeries(next);
|
|
9355
9589
|
this.delegateMethod("setOption", next, {
|
|
9356
9590
|
notMerge: !!notMerge,
|
|
9357
9591
|
lazyUpdate: !!lazyUpdate
|
|
@@ -9518,6 +9752,7 @@ const _sfc_main$3 = {
|
|
|
9518
9752
|
const next = this.getOptionsWithTheme(val);
|
|
9519
9753
|
this._applySavedDataZoomToOptions(next, savedDataZoom);
|
|
9520
9754
|
this._preserveGraphic(next);
|
|
9755
|
+
this._preserveTrendSeries(next);
|
|
9521
9756
|
this.chart.setOption(next, {
|
|
9522
9757
|
notMerge: this.skipClone || val !== oldVal
|
|
9523
9758
|
});
|
|
@@ -9613,7 +9848,7 @@ const _hoisted_1$3 = { class: "echarts" };
|
|
|
9613
9848
|
function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
|
9614
9849
|
return openBlock(), createElementBlock("div", _hoisted_1$3);
|
|
9615
9850
|
}
|
|
9616
|
-
const resizeEcharts = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3], ["__scopeId", "data-v-
|
|
9851
|
+
const resizeEcharts = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3], ["__scopeId", "data-v-5b44c8a6"]]);
|
|
9617
9852
|
const DRAW_POINT_MIN = 600;
|
|
9618
9853
|
const DRAW_POINT_MAX = 1800;
|
|
9619
9854
|
function getSeriesDrawThreshold(laneHeightPx) {
|
|
@@ -9994,6 +10229,7 @@ const _sfc_main$2 = {
|
|
|
9994
10229
|
selectedParamId: null,
|
|
9995
10230
|
// 当前选中的泳道ID(只有该泳道显示缺失点、区块、区块点)
|
|
9996
10231
|
activeLaneId: null,
|
|
10232
|
+
activeLaneIds: [],
|
|
9997
10233
|
currentMarkAreaIndex: -1,
|
|
9998
10234
|
// 每个泳道的选中点对数组,每对包含两个点形成区块,与 markArea 通过 markAreaId 关联
|
|
9999
10235
|
laneSelectedPointPairs: {},
|
|
@@ -10030,6 +10266,8 @@ const _sfc_main$2 = {
|
|
|
10030
10266
|
this._isPanning = false;
|
|
10031
10267
|
this._isZooming = false;
|
|
10032
10268
|
this._zoomIdleTimer = 0;
|
|
10269
|
+
this._geoClickTimer = 0;
|
|
10270
|
+
this._laneZrHandlers = /* @__PURE__ */ Object.create(null);
|
|
10033
10271
|
this._connectDetached = false;
|
|
10034
10272
|
this._savedConnectGroups = null;
|
|
10035
10273
|
this._tipHtmlBucket = "";
|
|
@@ -10039,7 +10277,7 @@ const _sfc_main$2 = {
|
|
|
10039
10277
|
this._pointerRaf = 0;
|
|
10040
10278
|
const pending = this._pendingPointer;
|
|
10041
10279
|
if (!pending || !this.pointerInChartArea) return;
|
|
10042
|
-
const { chart, x, y } = pending;
|
|
10280
|
+
const { chart, x, y, clientY } = pending;
|
|
10043
10281
|
if (!chart || chart.isDisposed()) {
|
|
10044
10282
|
this._pendingPointer = null;
|
|
10045
10283
|
return;
|
|
@@ -10078,7 +10316,18 @@ const _sfc_main$2 = {
|
|
|
10078
10316
|
clearTimeout(this._zoomIdleTimer);
|
|
10079
10317
|
this._zoomIdleTimer = 0;
|
|
10080
10318
|
}
|
|
10081
|
-
if (this.
|
|
10319
|
+
if (this._geoClickTimer) {
|
|
10320
|
+
clearTimeout(this._geoClickTimer);
|
|
10321
|
+
this._geoClickTimer = 0;
|
|
10322
|
+
}
|
|
10323
|
+
Object.keys(this._laneZrHandlers || {}).forEach((laneId) => {
|
|
10324
|
+
this._unbindLaneZrEvents(laneId);
|
|
10325
|
+
});
|
|
10326
|
+
this._laneZrHandlers = /* @__PURE__ */ Object.create(null);
|
|
10327
|
+
if (this.trendLineManager) {
|
|
10328
|
+
this.trendLineManager.destroy();
|
|
10329
|
+
this.trendLineManager = null;
|
|
10330
|
+
}
|
|
10082
10331
|
if (this._pointerRaf) {
|
|
10083
10332
|
cancelAnimationFrame(this._pointerRaf);
|
|
10084
10333
|
this._pointerRaf = 0;
|
|
@@ -10099,6 +10348,7 @@ const _sfc_main$2 = {
|
|
|
10099
10348
|
this.attachChartConnect();
|
|
10100
10349
|
this.unbindChartPointerSync();
|
|
10101
10350
|
echarts.disConnect(this.group);
|
|
10351
|
+
this.chartRefMap = /* @__PURE__ */ Object.create(null);
|
|
10102
10352
|
this.clearEcharts();
|
|
10103
10353
|
if (this.resizeObserver) {
|
|
10104
10354
|
this.resizeObserver.disconnect();
|
|
@@ -10118,6 +10368,7 @@ const _sfc_main$2 = {
|
|
|
10118
10368
|
async laneWidthChange(widthMap) {
|
|
10119
10369
|
this.laneWidthMap = widthMap || {};
|
|
10120
10370
|
await this.$nextTick();
|
|
10371
|
+
if (this._isUnmounted) return;
|
|
10121
10372
|
this.updateLanesChartOption();
|
|
10122
10373
|
},
|
|
10123
10374
|
// 曲线上方对数刻度:边控关则只藏尺。8.22对数轴
|
|
@@ -10182,43 +10433,77 @@ const _sfc_main$2 = {
|
|
|
10182
10433
|
flex: "1"
|
|
10183
10434
|
});
|
|
10184
10435
|
}
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
|
|
10436
|
+
if (this.isGeomechanical) {
|
|
10437
|
+
style.boxSizing = "border-box";
|
|
10438
|
+
style.border = this.isLaneSelected(laneId) ? "1px solid #F86C59" : "1px solid transparent";
|
|
10439
|
+
} else if (this.isLaneTrendDrawById(laneId)) {
|
|
10188
10440
|
style.boxSizing = "border-box";
|
|
10189
|
-
style.border =
|
|
10441
|
+
style.border = "1px solid #F86C59";
|
|
10190
10442
|
}
|
|
10191
10443
|
return style;
|
|
10192
10444
|
},
|
|
10445
|
+
// 按引用摘掉 click/dblclick,避免 zr.off(类型) 误拆趋势线 dblclick。8.25
|
|
10446
|
+
_unbindLaneZrEvents(laneId) {
|
|
10447
|
+
const rec = this._laneZrHandlers && this._laneZrHandlers[laneId];
|
|
10448
|
+
if (!rec) return;
|
|
10449
|
+
try {
|
|
10450
|
+
const chart = rec.chart;
|
|
10451
|
+
if (chart && typeof chart.getZr === "function" && !chart.isDisposed()) {
|
|
10452
|
+
const zr = chart.getZr();
|
|
10453
|
+
if (zr) {
|
|
10454
|
+
if (rec.onContext) zr.off("contextmenu", rec.onContext);
|
|
10455
|
+
if (rec.onClick) zr.off("click", rec.onClick);
|
|
10456
|
+
if (rec.onDbl) zr.off("dblclick", rec.onDbl);
|
|
10457
|
+
}
|
|
10458
|
+
}
|
|
10459
|
+
} catch (e) {
|
|
10460
|
+
}
|
|
10461
|
+
rec.chart = null;
|
|
10462
|
+
rec.onContext = null;
|
|
10463
|
+
rec.onClick = null;
|
|
10464
|
+
rec.onDbl = null;
|
|
10465
|
+
delete this._laneZrHandlers[laneId];
|
|
10466
|
+
},
|
|
10467
|
+
_bindLaneZrEvents(laneId, chart) {
|
|
10468
|
+
this._unbindLaneZrEvents(laneId);
|
|
10469
|
+
if (!chart || chart.isDisposed()) return;
|
|
10470
|
+
let zr;
|
|
10471
|
+
try {
|
|
10472
|
+
zr = chart.getZr();
|
|
10473
|
+
} catch (e) {
|
|
10474
|
+
return;
|
|
10475
|
+
}
|
|
10476
|
+
if (!zr) return;
|
|
10477
|
+
const onContext = (e) => this.handleChartRightClick(e, laneId);
|
|
10478
|
+
const onClick = (e) => this.handleChartClick(e, laneId);
|
|
10479
|
+
const onDbl = (e) => this.handleChartDblClick(e, laneId);
|
|
10480
|
+
zr.on("contextmenu", onContext);
|
|
10481
|
+
zr.on("click", onClick);
|
|
10482
|
+
zr.on("dblclick", onDbl);
|
|
10483
|
+
this._laneZrHandlers[laneId] = { chart, onContext, onClick, onDbl };
|
|
10484
|
+
},
|
|
10193
10485
|
setChartRef(laneId, el) {
|
|
10194
10486
|
if (el) {
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
this.
|
|
10487
|
+
const prev = this.chartRefMap[laneId];
|
|
10488
|
+
if (prev && prev.chart && prev.chart !== el.chart) {
|
|
10489
|
+
this._unbindLaneZrEvents(laneId);
|
|
10198
10490
|
}
|
|
10199
10491
|
this.chartRefMap[laneId] = el;
|
|
10200
|
-
|
|
10201
|
-
el.chart && el.chart.getZr().on("click", (e) => this.handleChartClick(e, laneId));
|
|
10492
|
+
if (el.chart) this._bindLaneZrEvents(laneId, el.chart);
|
|
10202
10493
|
if (el.chart && this.trendLineManager) {
|
|
10203
10494
|
this.trendLineManager.bindChart(laneId, el.chart);
|
|
10204
10495
|
}
|
|
10205
10496
|
} else if (this.chartRefMap[laneId]) {
|
|
10206
10497
|
if (this.trendLineManager) this.trendLineManager.unbindChart(laneId);
|
|
10207
|
-
this.
|
|
10208
|
-
this.chartRefMap[laneId].chart && this.chartRefMap[laneId].chart.getZr().off("click");
|
|
10498
|
+
this._unbindLaneZrEvents(laneId);
|
|
10209
10499
|
delete this.chartRefMap[laneId];
|
|
10210
10500
|
}
|
|
10211
10501
|
},
|
|
10212
10502
|
handleChartInited(laneId, chart) {
|
|
10213
|
-
|
|
10214
|
-
this.chartRefMap[laneId].chart.getZr().off("contextmenu");
|
|
10215
|
-
this.chartRefMap[laneId].chart.getZr().off("click");
|
|
10216
|
-
}
|
|
10217
|
-
chart.getZr().on("contextmenu", (e) => this.handleChartRightClick(e, laneId));
|
|
10218
|
-
chart.getZr().on("click", (e) => this.handleChartClick(e, laneId));
|
|
10503
|
+
this._bindLaneZrEvents(laneId, chart);
|
|
10219
10504
|
if (this.trendLineManager) {
|
|
10220
10505
|
this.trendLineManager.bindChart(laneId, chart);
|
|
10221
|
-
this.applyLineListData();
|
|
10506
|
+
if ((this.lineListData || []).length) this.applyLineListData();
|
|
10222
10507
|
this.trendLineManager.scheduleRender();
|
|
10223
10508
|
}
|
|
10224
10509
|
this.scheduleConnectAllCharts();
|
|
@@ -10230,14 +10515,24 @@ const _sfc_main$2 = {
|
|
|
10230
10515
|
this.getConnectedCharts().forEach((chart) => {
|
|
10231
10516
|
if (!chart || chart.isDisposed()) return;
|
|
10232
10517
|
const laneId = this.findLaneIdByChart(chart);
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10518
|
+
const next = this.buildInsideDataZoom(
|
|
10519
|
+
!!enabled,
|
|
10520
|
+
this.dataZoomFilterModeForLane(this.findLaneById(laneId))
|
|
10521
|
+
);
|
|
10522
|
+
try {
|
|
10523
|
+
const dz = chart.getModel().getComponent("dataZoom", 0);
|
|
10524
|
+
const opt = dz && dz.option;
|
|
10525
|
+
if (opt) {
|
|
10526
|
+
if (opt.start != null) next.start = opt.start;
|
|
10527
|
+
if (opt.end != null) next.end = opt.end;
|
|
10528
|
+
if (opt.startValue != null) next.startValue = opt.startValue;
|
|
10529
|
+
if (opt.endValue != null) next.endValue = opt.endValue;
|
|
10530
|
+
}
|
|
10531
|
+
const skip = this.trendLineManager && this.trendLineManager.dataZoomSeriesIndex(chart);
|
|
10532
|
+
if (skip && skip.length) next.seriesIndex = skip;
|
|
10533
|
+
} catch (e) {
|
|
10534
|
+
}
|
|
10535
|
+
chart.setOption({ dataZoom: [next] }, { silent: true, lazyUpdate: false });
|
|
10241
10536
|
});
|
|
10242
10537
|
},
|
|
10243
10538
|
getConnectedCharts() {
|
|
@@ -10249,7 +10544,7 @@ const _sfc_main$2 = {
|
|
|
10249
10544
|
// 趋势线控制点右键菜单(删除控制点) 8.21
|
|
10250
10545
|
showTrendKnotContextMenu(e, payload) {
|
|
10251
10546
|
this.currentContextMenuType = "trendKnot";
|
|
10252
|
-
this.currentPointInfo = payload;
|
|
10547
|
+
this.currentPointInfo = markRaw(payload);
|
|
10253
10548
|
this.currentContextMenuItems = [{ label: "删除控制点", action: "deleteTrendKnot" }];
|
|
10254
10549
|
this.calculateContextMenuPosition(e);
|
|
10255
10550
|
this.contextMenuVisible = true;
|
|
@@ -10282,6 +10577,85 @@ const _sfc_main$2 = {
|
|
|
10282
10577
|
resetAllTrendLines() {
|
|
10283
10578
|
if (this.trendLineManager) this.trendLineManager.resetAllTrendLines();
|
|
10284
10579
|
},
|
|
10580
|
+
isLaneSelected(laneId) {
|
|
10581
|
+
return laneId != null && (this.activeLaneIds || []).some((id) => id === laneId);
|
|
10582
|
+
},
|
|
10583
|
+
addLaneSelection(laneId) {
|
|
10584
|
+
if (laneId == null) return false;
|
|
10585
|
+
this.activeLaneId = laneId;
|
|
10586
|
+
if (this.isLaneSelected(laneId)) return false;
|
|
10587
|
+
this.activeLaneIds = this.activeLaneIds.concat([laneId]);
|
|
10588
|
+
return true;
|
|
10589
|
+
},
|
|
10590
|
+
removeLaneSelection(laneId) {
|
|
10591
|
+
if (!this.isLaneSelected(laneId)) return;
|
|
10592
|
+
this.activeLaneIds = (this.activeLaneIds || []).filter((id) => id !== laneId);
|
|
10593
|
+
if (this.activeLaneId === laneId) {
|
|
10594
|
+
this.activeLaneId = this.activeLaneIds.length ? this.activeLaneIds[this.activeLaneIds.length - 1] : null;
|
|
10595
|
+
}
|
|
10596
|
+
},
|
|
10597
|
+
// 退出编辑:清掉全部选中红框,不挂新监听。8.25
|
|
10598
|
+
clearActiveLane() {
|
|
10599
|
+
this._clearGeoClickTimer();
|
|
10600
|
+
this._geoSelectClickAt = 0;
|
|
10601
|
+
this._geoSelectLaneId = null;
|
|
10602
|
+
this._lastBlankClickTime = null;
|
|
10603
|
+
this._lastBlankClickLaneId = null;
|
|
10604
|
+
const ids = (this.activeLaneIds || []).slice();
|
|
10605
|
+
if (this.selectedPoints.length > 0 && this.selectedLaneId) {
|
|
10606
|
+
if (this.laneSelectedPointPairs[this.selectedLaneId]) {
|
|
10607
|
+
this.laneSelectedPointPairs[this.selectedLaneId].pop();
|
|
10608
|
+
}
|
|
10609
|
+
this.selectedPoints = [];
|
|
10610
|
+
this.selectedLaneId = null;
|
|
10611
|
+
this.selectedParamId = null;
|
|
10612
|
+
}
|
|
10613
|
+
this.activeLaneIds = [];
|
|
10614
|
+
this.activeLaneId = null;
|
|
10615
|
+
if (!ids.length) return;
|
|
10616
|
+
this.updateLanesChartOption().then(() => {
|
|
10617
|
+
if (this._isUnmounted) return;
|
|
10618
|
+
ids.forEach((id) => this.showSelectedPointScatter(id));
|
|
10619
|
+
});
|
|
10620
|
+
},
|
|
10621
|
+
// 切趋势线:只保留当前曲线所在道;单击其它道仍可再选中。8.25
|
|
10622
|
+
selectLaneByParamId(paramId) {
|
|
10623
|
+
if (!this.isGeomechanical) return;
|
|
10624
|
+
if (paramId == null || paramId === "") {
|
|
10625
|
+
this.clearActiveLane();
|
|
10626
|
+
return;
|
|
10627
|
+
}
|
|
10628
|
+
const lanes = this.currentTemplate && this.currentTemplate.lanes || [];
|
|
10629
|
+
let laneId = null;
|
|
10630
|
+
for (let i = 0; i < lanes.length; i++) {
|
|
10631
|
+
const lane = lanes[i];
|
|
10632
|
+
if ((lane.lines || []).some((line) => String(line.paramId) === String(paramId))) {
|
|
10633
|
+
laneId = lane.laneId;
|
|
10634
|
+
break;
|
|
10635
|
+
}
|
|
10636
|
+
}
|
|
10637
|
+
if (!laneId) return;
|
|
10638
|
+
const prevIds = (this.activeLaneIds || []).slice();
|
|
10639
|
+
if (prevIds.length === 1 && prevIds[0] === laneId) {
|
|
10640
|
+
this.activeLaneId = laneId;
|
|
10641
|
+
return;
|
|
10642
|
+
}
|
|
10643
|
+
if (this.selectedPoints.length > 0 && this.selectedLaneId && this.selectedLaneId !== laneId) {
|
|
10644
|
+
if (this.laneSelectedPointPairs[this.selectedLaneId]) {
|
|
10645
|
+
this.laneSelectedPointPairs[this.selectedLaneId].pop();
|
|
10646
|
+
}
|
|
10647
|
+
this.selectedPoints = [];
|
|
10648
|
+
this.selectedLaneId = null;
|
|
10649
|
+
this.selectedParamId = null;
|
|
10650
|
+
}
|
|
10651
|
+
this.activeLaneIds = [laneId];
|
|
10652
|
+
this.activeLaneId = laneId;
|
|
10653
|
+
this.updateLanesChartOption().then(() => {
|
|
10654
|
+
if (this._isUnmounted) return;
|
|
10655
|
+
prevIds.forEach((id) => this.showSelectedPointScatter(id));
|
|
10656
|
+
this.showSelectedPointScatter(laneId);
|
|
10657
|
+
});
|
|
10658
|
+
},
|
|
10285
10659
|
// 根据 paramId 判断曲线是否可见(isUsed === '1')
|
|
10286
10660
|
isLineVisibleByParamId(paramId) {
|
|
10287
10661
|
const lanes = this.currentTemplate && this.currentTemplate.lanes || [];
|
|
@@ -10400,7 +10774,7 @@ const _sfc_main$2 = {
|
|
|
10400
10774
|
const sm = seriesList[s];
|
|
10401
10775
|
const option = sm.option || {};
|
|
10402
10776
|
const name = this.unwrapEchartsValue(sm.name);
|
|
10403
|
-
if (name === "helper" || name === "log-grid") continue;
|
|
10777
|
+
if (name === "helper" || name === "log-grid" || name === "trend") continue;
|
|
10404
10778
|
const type = sm.subType || this.unwrapEchartsValue(option.type);
|
|
10405
10779
|
if (type && type !== "line") continue;
|
|
10406
10780
|
const tip = option.tooltip;
|
|
@@ -10561,6 +10935,7 @@ const _sfc_main$2 = {
|
|
|
10561
10935
|
if (!series || !Array.isArray(series.data) || !series.data.length) return false;
|
|
10562
10936
|
if (this.seriesDisplayName(series) === "helper") return false;
|
|
10563
10937
|
if (this.seriesDisplayName(series) === "log-grid") return false;
|
|
10938
|
+
if (this.seriesDisplayName(series) === "trend") return false;
|
|
10564
10939
|
const type = this.seriesTypeName(series);
|
|
10565
10940
|
if (type && type !== "line") return false;
|
|
10566
10941
|
if (this.seriesTooltipHidden(series)) return false;
|
|
@@ -10715,8 +11090,8 @@ const _sfc_main$2 = {
|
|
|
10715
11090
|
el.style.transform = `translate3d(0, ${top}px, 0)`;
|
|
10716
11091
|
if (!this.crosshairVisible) this.crosshairVisible = true;
|
|
10717
11092
|
},
|
|
10718
|
-
schedulePointerSync(chart, x, y) {
|
|
10719
|
-
this._pendingPointer = { chart, x, y };
|
|
11093
|
+
schedulePointerSync(chart, x, y, clientY) {
|
|
11094
|
+
this._pendingPointer = { chart, x, y, clientY };
|
|
10720
11095
|
if (this._pointerRaf) return;
|
|
10721
11096
|
this._pointerRaf = requestAnimationFrame(this._flushPointerSync);
|
|
10722
11097
|
},
|
|
@@ -10856,6 +11231,7 @@ const _sfc_main$2 = {
|
|
|
10856
11231
|
},
|
|
10857
11232
|
startChartPan() {
|
|
10858
11233
|
if (!this.isGeomechanical || this._isPanning) return;
|
|
11234
|
+
if (this._chartPanLocked) return;
|
|
10859
11235
|
this._isPanning = true;
|
|
10860
11236
|
this.attachChartConnect();
|
|
10861
11237
|
this.hideLaneTooltipsForPan();
|
|
@@ -10879,6 +11255,7 @@ const _sfc_main$2 = {
|
|
|
10879
11255
|
this._zoomIdleTimer = 0;
|
|
10880
11256
|
if (!this._isZooming) return;
|
|
10881
11257
|
this._isZooming = false;
|
|
11258
|
+
if (!this._isPanning && this.trendLineManager) this.trendLineManager.endFollowView();
|
|
10882
11259
|
this.restorePointerAfterInteract();
|
|
10883
11260
|
},
|
|
10884
11261
|
hideAllLaneTooltips(event) {
|
|
@@ -10955,7 +11332,8 @@ const _sfc_main$2 = {
|
|
|
10955
11332
|
this.schedulePointerSync(
|
|
10956
11333
|
chart,
|
|
10957
11334
|
e.offsetX ?? ((_a = e.event) == null ? void 0 : _a.offsetX),
|
|
10958
|
-
e.offsetY ?? ((_b = e.event) == null ? void 0 : _b.offsetY)
|
|
11335
|
+
e.offsetY ?? ((_b = e.event) == null ? void 0 : _b.offsetY),
|
|
11336
|
+
native.clientY
|
|
10959
11337
|
);
|
|
10960
11338
|
};
|
|
10961
11339
|
zr.on("mousedown", onDown);
|
|
@@ -10995,11 +11373,13 @@ const _sfc_main$2 = {
|
|
|
10995
11373
|
if (this.trendLineManager) this.trendLineManager.hydrateFromTemplate(template);
|
|
10996
11374
|
this.applyLineListData();
|
|
10997
11375
|
await this.$nextTick();
|
|
11376
|
+
if (this._isUnmounted) return;
|
|
10998
11377
|
this.updateLanesChartOption();
|
|
10999
11378
|
},
|
|
11000
11379
|
// 线段变化
|
|
11001
11380
|
async lineChange() {
|
|
11002
11381
|
await this.$nextTick();
|
|
11382
|
+
if (this._isUnmounted) return;
|
|
11003
11383
|
this.updateLanesChartOption();
|
|
11004
11384
|
},
|
|
11005
11385
|
// 初始化窗口大小范围以及windowSize默认值
|
|
@@ -11174,10 +11554,10 @@ const _sfc_main$2 = {
|
|
|
11174
11554
|
ref.mergeOptions(option, true, false, true);
|
|
11175
11555
|
},
|
|
11176
11556
|
// 判断指定泳道是否应该显示tooltip内容
|
|
11177
|
-
//
|
|
11557
|
+
// 地应力:无选中时所有泳道显示;有选中时已选中的多道都显示。8.25
|
|
11178
11558
|
shouldShowTooltipContent(laneId) {
|
|
11179
11559
|
if (!this.showTooltip) return false;
|
|
11180
|
-
if (this.isGeomechanical && this.
|
|
11560
|
+
if (this.isGeomechanical && (this.activeLaneIds || []).length && !this.isLaneSelected(laneId)) {
|
|
11181
11561
|
return false;
|
|
11182
11562
|
}
|
|
11183
11563
|
return true;
|
|
@@ -11633,7 +12013,7 @@ const _sfc_main$2 = {
|
|
|
11633
12013
|
return { data: [[x, group.min], [x, group.max]] };
|
|
11634
12014
|
}
|
|
11635
12015
|
const type = sm.subType || this.unwrapEchartsValue(opt.type);
|
|
11636
|
-
if (name === "log-grid" || type !== "line") return {};
|
|
12016
|
+
if (name === "log-grid" || name === "trend" || type !== "line") return {};
|
|
11637
12017
|
const paramId = this.unwrapEchartsValue(opt.paramId);
|
|
11638
12018
|
if (paramId == null) return {};
|
|
11639
12019
|
const cacheKey = `${gi}:${paramId}:${isLog ? 1 : 0}`;
|
|
@@ -11665,7 +12045,6 @@ const _sfc_main$2 = {
|
|
|
11665
12045
|
} catch (e) {
|
|
11666
12046
|
}
|
|
11667
12047
|
});
|
|
11668
|
-
if (this.trendLineManager) this.trendLineManager.scheduleZoomRender();
|
|
11669
12048
|
},
|
|
11670
12049
|
// 处理键盘按下事件
|
|
11671
12050
|
handleKeyDown(e) {
|
|
@@ -12250,6 +12629,7 @@ const _sfc_main$2 = {
|
|
|
12250
12629
|
},
|
|
12251
12630
|
// 更新泳道图表选项
|
|
12252
12631
|
async updateLanesChartOption(transferData) {
|
|
12632
|
+
if (this._isUnmounted) return;
|
|
12253
12633
|
if (this.isUpdatingChart) {
|
|
12254
12634
|
this.pendingChartUpdate = true;
|
|
12255
12635
|
return;
|
|
@@ -12567,7 +12947,7 @@ const _sfc_main$2 = {
|
|
|
12567
12947
|
if (rangeAreaSeries) {
|
|
12568
12948
|
option.series.push(rangeAreaSeries);
|
|
12569
12949
|
}
|
|
12570
|
-
if (lineInfo.isUsed === "1" && this.isGeomechanical && lane.laneId
|
|
12950
|
+
if (lineInfo.isUsed === "1" && this.isGeomechanical && this.isLaneSelected(lane.laneId)) {
|
|
12571
12951
|
const boundaryPoints = this.findMissingDataBoundaryPoints(
|
|
12572
12952
|
this.plotSeries(groupSeriesData, isLogScale)
|
|
12573
12953
|
);
|
|
@@ -12720,12 +13100,17 @@ const _sfc_main$2 = {
|
|
|
12720
13100
|
option.tooltip.extraCssText = "pointer-events: none !important;";
|
|
12721
13101
|
option.tooltip.formatter = () => this.renderLaneTooltipHtml(laneId);
|
|
12722
13102
|
}
|
|
13103
|
+
if (this.trendLineManager) this.trendLineManager.appendSeriesToOption(option, lane);
|
|
12723
13104
|
this.updateOptionsByLineId(lane.laneId, option);
|
|
12724
13105
|
}
|
|
12725
13106
|
} catch (error) {
|
|
12726
13107
|
console.error("updateLanesChartOption error:", error);
|
|
12727
13108
|
} finally {
|
|
12728
13109
|
this.isUpdatingChart = false;
|
|
13110
|
+
if (this._isUnmounted) {
|
|
13111
|
+
this.pendingChartUpdate = false;
|
|
13112
|
+
return;
|
|
13113
|
+
}
|
|
12729
13114
|
this.scheduleConnectAllCharts();
|
|
12730
13115
|
const lanesToRefresh = new Set(
|
|
12731
13116
|
Object.keys(this.laneSelectedPointPairs || {})
|
|
@@ -12733,6 +13118,7 @@ const _sfc_main$2 = {
|
|
|
12733
13118
|
if (this.selectedLaneId) lanesToRefresh.add(this.selectedLaneId);
|
|
12734
13119
|
if (lanesToRefresh.size > 0) {
|
|
12735
13120
|
this.$nextTick(() => {
|
|
13121
|
+
if (this._isUnmounted) return;
|
|
12736
13122
|
lanesToRefresh.forEach((lid) => {
|
|
12737
13123
|
this.showSelectedPointScatter(lid);
|
|
12738
13124
|
});
|
|
@@ -12741,13 +13127,10 @@ const _sfc_main$2 = {
|
|
|
12741
13127
|
if (this.pendingChartUpdate) {
|
|
12742
13128
|
this.pendingChartUpdate = false;
|
|
12743
13129
|
this.$nextTick(() => {
|
|
13130
|
+
if (this._isUnmounted) return;
|
|
12744
13131
|
this.updateLanesChartOption(transferData);
|
|
12745
13132
|
});
|
|
12746
13133
|
}
|
|
12747
|
-
if (this.trendLineManager) {
|
|
12748
|
-
this.trendLineManager.scheduleZoomRender();
|
|
12749
|
-
this.$nextTick(() => this.trendLineManager.scheduleZoomRender());
|
|
12750
|
-
}
|
|
12751
13134
|
}
|
|
12752
13135
|
},
|
|
12753
13136
|
/**
|
|
@@ -13040,85 +13423,172 @@ const _sfc_main$2 = {
|
|
|
13040
13423
|
}
|
|
13041
13424
|
return boundaryPoints;
|
|
13042
13425
|
},
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
const
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
if (
|
|
13057
|
-
|
|
13426
|
+
// 只把点击附近的点转成像素。全量 convertToPixel 会堵住主线程,双击 500ms 对不上。8.25
|
|
13427
|
+
findClosestGeoLineHit(chart, option, pointInPixel, pixelThreshold, laneId) {
|
|
13428
|
+
var _a;
|
|
13429
|
+
const threshold = pixelThreshold || 10;
|
|
13430
|
+
const px = pointInPixel[0];
|
|
13431
|
+
const py = pointInPixel[1];
|
|
13432
|
+
const seriesList = option && option.series || [];
|
|
13433
|
+
let closest = null;
|
|
13434
|
+
let closestDistance = threshold;
|
|
13435
|
+
for (let i = 0; i < seriesList.length; i++) {
|
|
13436
|
+
const series2 = seriesList[i];
|
|
13437
|
+
if (!series2 || series2.type !== "line") continue;
|
|
13438
|
+
const name = Array.isArray(series2.name) ? series2.name[0] : series2.name;
|
|
13439
|
+
if (name === "helper" || name === "log-grid" || name === "trend") continue;
|
|
13440
|
+
const id = String(series2.id || "");
|
|
13441
|
+
if (id.indexOf("trend_") === 0) continue;
|
|
13442
|
+
let clickData;
|
|
13443
|
+
try {
|
|
13444
|
+
clickData = chart.convertFromPixel({ seriesIndex: i }, [px, py]);
|
|
13445
|
+
} catch (err) {
|
|
13446
|
+
continue;
|
|
13058
13447
|
}
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
const series = option.series[i];
|
|
13072
|
-
if (series.name === "helper" || series.name === "log-grid") continue;
|
|
13073
|
-
if (series.type !== "line") continue;
|
|
13074
|
-
const data = series.data || [];
|
|
13448
|
+
if (!clickData || clickData.length < 2) continue;
|
|
13449
|
+
let yTol = Infinity;
|
|
13450
|
+
try {
|
|
13451
|
+
const offset = chart.convertFromPixel({ seriesIndex: i }, [px, py + threshold]);
|
|
13452
|
+
if (offset && offset.length >= 2) {
|
|
13453
|
+
const span = Math.abs(offset[1] - clickData[1]);
|
|
13454
|
+
if (Number.isFinite(span) && span > 0) yTol = span * 1.25;
|
|
13455
|
+
}
|
|
13456
|
+
} catch (err) {
|
|
13457
|
+
yTol = Infinity;
|
|
13458
|
+
}
|
|
13459
|
+
const data = series2.data || [];
|
|
13075
13460
|
for (let j = 0; j < data.length; j++) {
|
|
13076
|
-
const
|
|
13077
|
-
if (!
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
if (
|
|
13081
|
-
|
|
13082
|
-
const point = chart.convertToPixel({ seriesIndex: i }, pointValue);
|
|
13461
|
+
const item2 = data[j];
|
|
13462
|
+
if (!item2) continue;
|
|
13463
|
+
const pointValue2 = Array.isArray(item2) ? item2 : item2.value || [];
|
|
13464
|
+
if (!pointValue2 || pointValue2.length < 2) continue;
|
|
13465
|
+
if (Number.isFinite(yTol) && Math.abs(pointValue2[1] - clickData[1]) > yTol) continue;
|
|
13466
|
+
const point = chart.convertToPixel({ seriesIndex: i }, pointValue2);
|
|
13083
13467
|
if (!point) continue;
|
|
13084
|
-
const distance = Math.
|
|
13085
|
-
Math.pow(point[0] - pointInPixel[0], 2) + Math.pow(point[1] - pointInPixel[1], 2)
|
|
13086
|
-
);
|
|
13468
|
+
const distance = Math.hypot(point[0] - px, point[1] - py);
|
|
13087
13469
|
if (distance < closestDistance) {
|
|
13088
13470
|
closestDistance = distance;
|
|
13089
|
-
|
|
13090
|
-
const originalData = this.realTimeData.find(
|
|
13091
|
-
(d) => d[axisKey] == axisValue
|
|
13092
|
-
);
|
|
13093
|
-
const paramId = item.paramId || series.paramId;
|
|
13094
|
-
const lane = (this.currentTemplate && this.currentTemplate.lanes || []).find(
|
|
13095
|
-
(l) => l.laneId === laneId
|
|
13096
|
-
);
|
|
13097
|
-
const originalX = (item.rowData && item.rowData[paramId]) ?? (originalData && originalData[paramId]);
|
|
13098
|
-
option.xAxis && option.xAxis[series.xAxisIndex ?? 0] || {};
|
|
13099
|
-
const useOriginal = originalX != null && Number(originalX) > 0;
|
|
13100
|
-
const drawX = isLaneLogScale(lane) ? toLaneDrawX(
|
|
13101
|
-
useOriginal ? originalX : pointValue[0],
|
|
13102
|
-
lane
|
|
13103
|
-
) : pointValue[0];
|
|
13104
|
-
closestPoint = {
|
|
13105
|
-
...item,
|
|
13106
|
-
value: [drawX, pointValue[1], pointValue[2]],
|
|
13107
|
-
seriesIndex: i,
|
|
13108
|
-
dataIndex: j,
|
|
13109
|
-
paramId,
|
|
13110
|
-
lineId: item.lineId || series.lineId,
|
|
13111
|
-
color: series.color,
|
|
13112
|
-
laneId,
|
|
13113
|
-
depth: (originalData == null ? void 0 : originalData.depth) || null,
|
|
13114
|
-
timestamp: ((_c = originalData == null ? void 0 : originalData.timestamp) == null ? void 0 : _c.toString()) || null
|
|
13115
|
-
};
|
|
13471
|
+
closest = { item: item2, series: series2, seriesIndex: i, dataIndex: j, pointValue: pointValue2, distance };
|
|
13116
13472
|
}
|
|
13117
13473
|
}
|
|
13118
13474
|
}
|
|
13119
|
-
if (
|
|
13120
|
-
|
|
13475
|
+
if (!closest) return null;
|
|
13476
|
+
const axisKey = this.currentToolBarConfig.axisTypeList && this.currentToolBarConfig.axisTypeList[this.formCache.axisType] || (this.formCache.axisType === "time" ? "time" : "depth");
|
|
13477
|
+
const { item, series, seriesIndex, dataIndex, pointValue } = closest;
|
|
13478
|
+
const originalData = item && item.rowData || (this.realTimeData || []).find((d) => d[axisKey] == pointValue[1]);
|
|
13479
|
+
const paramId = item && item.paramId || series.paramId;
|
|
13480
|
+
const lane = (this.currentTemplate && this.currentTemplate.lanes || []).find(
|
|
13481
|
+
(l) => l.laneId === laneId
|
|
13482
|
+
);
|
|
13483
|
+
const originalX = (item.rowData && item.rowData[paramId]) ?? (originalData && originalData[paramId]);
|
|
13484
|
+
option.xAxis && option.xAxis[series.xAxisIndex ?? 0] || {};
|
|
13485
|
+
const useOriginal = originalX != null && Number(originalX) > 0;
|
|
13486
|
+
const drawX = isLaneLogScale(lane) ? toLaneDrawX(
|
|
13487
|
+
useOriginal ? originalX : pointValue[0],
|
|
13488
|
+
lane
|
|
13489
|
+
) : pointValue[0];
|
|
13490
|
+
return {
|
|
13491
|
+
...item,
|
|
13492
|
+
value: [drawX, pointValue[1], pointValue[2]],
|
|
13493
|
+
seriesIndex,
|
|
13494
|
+
dataIndex,
|
|
13495
|
+
paramId,
|
|
13496
|
+
lineId: item && item.lineId || series.lineId,
|
|
13497
|
+
color: series.color,
|
|
13498
|
+
laneId,
|
|
13499
|
+
depth: (originalData == null ? void 0 : originalData.depth) || null,
|
|
13500
|
+
timestamp: ((_a = originalData == null ? void 0 : originalData.timestamp) == null ? void 0 : _a.toString()) || null
|
|
13501
|
+
};
|
|
13502
|
+
},
|
|
13503
|
+
_clearGeoClickTimer() {
|
|
13504
|
+
if (this._geoClickTimer) {
|
|
13505
|
+
clearTimeout(this._geoClickTimer);
|
|
13506
|
+
this._geoClickTimer = 0;
|
|
13507
|
+
}
|
|
13508
|
+
},
|
|
13509
|
+
// 地应力:双击已选中泳道,只取消这一道,其它选中保留。8.25
|
|
13510
|
+
handleChartDblClick(e, laneId) {
|
|
13511
|
+
if (this._isUnmounted || !this.isGeomechanical) return;
|
|
13512
|
+
this._clearGeoClickTimer();
|
|
13513
|
+
if (!this.isLaneSelected(laneId)) return;
|
|
13514
|
+
if (this._geoSelectClickAt && this._geoSelectLaneId === laneId && Date.now() - this._geoSelectClickAt < 500) {
|
|
13515
|
+
return;
|
|
13516
|
+
}
|
|
13517
|
+
this.deselectGeoLane(laneId);
|
|
13518
|
+
},
|
|
13519
|
+
async deselectGeoLane(laneId) {
|
|
13520
|
+
const id = laneId != null ? laneId : this.activeLaneId;
|
|
13521
|
+
this._lastBlankClickTime = null;
|
|
13522
|
+
this._lastBlankClickLaneId = null;
|
|
13523
|
+
if (!id || !this.isLaneSelected(id)) return;
|
|
13524
|
+
if (this.selectedPoints.length > 0 && this.selectedLaneId === id) {
|
|
13525
|
+
if (this.laneSelectedPointPairs[this.selectedLaneId]) {
|
|
13526
|
+
this.laneSelectedPointPairs[this.selectedLaneId].pop();
|
|
13527
|
+
}
|
|
13528
|
+
this.selectedPoints = [];
|
|
13529
|
+
this.selectedLaneId = null;
|
|
13530
|
+
this.selectedParamId = null;
|
|
13531
|
+
}
|
|
13532
|
+
this.removeLaneSelection(id);
|
|
13533
|
+
await this.updateLanesChartOption();
|
|
13534
|
+
if (this._isUnmounted) return;
|
|
13535
|
+
this.showSelectedPointScatter(id);
|
|
13536
|
+
},
|
|
13537
|
+
async handleChartClick(e, laneId) {
|
|
13538
|
+
var _a, _b, _c, _d;
|
|
13539
|
+
if (this._isUnmounted) return;
|
|
13540
|
+
const clickAt = Date.now();
|
|
13541
|
+
const chartRef = this.getChartRefByLaneId(laneId);
|
|
13542
|
+
if (!chartRef || !chartRef.chart) return;
|
|
13543
|
+
const wasActiveLane = this.isLaneSelected(laneId);
|
|
13544
|
+
const trendConsumed = this.trendLineManager && this.trendLineManager.handleClick(e, laneId);
|
|
13545
|
+
if (!this.isGeomechanical) return;
|
|
13546
|
+
if (!wasActiveLane) {
|
|
13547
|
+
this._geoSelectClickAt = clickAt;
|
|
13548
|
+
this._geoSelectLaneId = laneId;
|
|
13549
|
+
this.addLaneSelection(laneId);
|
|
13550
|
+
await this.updateLanesChartOption();
|
|
13551
|
+
if (this._isUnmounted) return;
|
|
13552
|
+
this.showSelectedPointScatter(laneId);
|
|
13553
|
+
}
|
|
13554
|
+
if (trendConsumed) return;
|
|
13555
|
+
if (wasActiveLane) {
|
|
13556
|
+
this._clearGeoClickTimer();
|
|
13557
|
+
const offsetX = e.offsetX || ((_a = e.event) == null ? void 0 : _a.offsetX);
|
|
13558
|
+
const offsetY = e.offsetY || ((_b = e.event) == null ? void 0 : _b.offsetY);
|
|
13559
|
+
this._geoClickTimer = setTimeout(() => {
|
|
13560
|
+
this._geoClickTimer = 0;
|
|
13561
|
+
if (this._isUnmounted) return;
|
|
13562
|
+
this.processGeoPointOrBlank(laneId, offsetX, offsetY, clickAt, true);
|
|
13563
|
+
}, 280);
|
|
13564
|
+
return;
|
|
13121
13565
|
}
|
|
13566
|
+
const pointInPixel = [
|
|
13567
|
+
e.offsetX || ((_c = e.event) == null ? void 0 : _c.offsetX),
|
|
13568
|
+
e.offsetY || ((_d = e.event) == null ? void 0 : _d.offsetY)
|
|
13569
|
+
];
|
|
13570
|
+
await this.processGeoPointOrBlank(
|
|
13571
|
+
laneId,
|
|
13572
|
+
pointInPixel[0],
|
|
13573
|
+
pointInPixel[1],
|
|
13574
|
+
clickAt,
|
|
13575
|
+
false
|
|
13576
|
+
);
|
|
13577
|
+
},
|
|
13578
|
+
async processGeoPointOrBlank(laneId, offsetX, offsetY, clickAt, wasActiveLane) {
|
|
13579
|
+
if (this._isUnmounted) return;
|
|
13580
|
+
const chartRef = this.getChartRefByLaneId(laneId);
|
|
13581
|
+
if (!chartRef || !chartRef.chart) return;
|
|
13582
|
+
const chart = chartRef.chart;
|
|
13583
|
+
const option = this.readChartOptionRefs(chart);
|
|
13584
|
+
const closestPoint = this.findClosestGeoLineHit(
|
|
13585
|
+
chart,
|
|
13586
|
+
option,
|
|
13587
|
+
[offsetX, offsetY],
|
|
13588
|
+
10,
|
|
13589
|
+
laneId
|
|
13590
|
+
);
|
|
13591
|
+
const clickedPoint = closestPoint || null;
|
|
13122
13592
|
if (clickedPoint) {
|
|
13123
13593
|
this._lastBlankClickTime = null;
|
|
13124
13594
|
this._lastBlankClickLaneId = null;
|
|
@@ -13177,18 +13647,19 @@ const _sfc_main$2 = {
|
|
|
13177
13647
|
this.showSelectedPointScatter(laneId);
|
|
13178
13648
|
}
|
|
13179
13649
|
if (wasActiveLane) {
|
|
13180
|
-
const now =
|
|
13650
|
+
const now = clickAt;
|
|
13181
13651
|
if (this._lastBlankClickLaneId === laneId && this._lastBlankClickTime && now - this._lastBlankClickTime < 500) {
|
|
13182
13652
|
this._lastBlankClickTime = null;
|
|
13183
13653
|
this._lastBlankClickLaneId = null;
|
|
13184
|
-
if (this.selectedPoints.length > 0 && this.selectedLaneId) {
|
|
13654
|
+
if (this.selectedPoints.length > 0 && this.selectedLaneId === laneId) {
|
|
13185
13655
|
this.laneSelectedPointPairs[this.selectedLaneId].pop();
|
|
13186
13656
|
this.selectedPoints = [];
|
|
13187
13657
|
this.selectedLaneId = null;
|
|
13188
13658
|
this.selectedParamId = null;
|
|
13189
13659
|
}
|
|
13190
|
-
this.
|
|
13660
|
+
this.removeLaneSelection(laneId);
|
|
13191
13661
|
await this.updateLanesChartOption();
|
|
13662
|
+
if (this._isUnmounted) return;
|
|
13192
13663
|
} else {
|
|
13193
13664
|
this._lastBlankClickTime = now;
|
|
13194
13665
|
this._lastBlankClickLaneId = laneId;
|
|
@@ -13199,12 +13670,13 @@ const _sfc_main$2 = {
|
|
|
13199
13670
|
}
|
|
13200
13671
|
}
|
|
13201
13672
|
await this.$nextTick();
|
|
13673
|
+
if (this._isUnmounted) return;
|
|
13202
13674
|
this.showSelectedPointScatter(laneId);
|
|
13203
13675
|
},
|
|
13204
13676
|
// 收集某泳道所有需要展示 scatter 的点:已完成区块的两个点 + 进行中的第一个点
|
|
13205
|
-
//
|
|
13677
|
+
// 地应力已选中的泳道都收集并显示。8.25
|
|
13206
13678
|
collectScatterPointsForLane(laneId) {
|
|
13207
|
-
if (!this.isGeomechanical ||
|
|
13679
|
+
if (!this.isGeomechanical || !this.isLaneSelected(laneId)) return [];
|
|
13208
13680
|
const points = [];
|
|
13209
13681
|
const pairs = this.laneSelectedPointPairs[laneId] || [];
|
|
13210
13682
|
pairs.forEach((pair) => {
|
|
@@ -13333,15 +13805,9 @@ const _sfc_main$2 = {
|
|
|
13333
13805
|
return;
|
|
13334
13806
|
}
|
|
13335
13807
|
if (!this.isGeomechanical) return;
|
|
13336
|
-
if (this.
|
|
13337
|
-
|
|
13338
|
-
this.activeLaneId = laneId;
|
|
13808
|
+
if (!this.isLaneSelected(laneId)) {
|
|
13809
|
+
this.addLaneSelection(laneId);
|
|
13339
13810
|
this.updateLanesChartOption();
|
|
13340
|
-
if (prevActiveLaneId) {
|
|
13341
|
-
this.$nextTick(() => {
|
|
13342
|
-
this.showSelectedPointScatter(prevActiveLaneId);
|
|
13343
|
-
});
|
|
13344
|
-
}
|
|
13345
13811
|
}
|
|
13346
13812
|
const chart = chartRef.chart;
|
|
13347
13813
|
const pointInPixel = [
|
|
@@ -13956,7 +14422,7 @@ const _sfc_main$2 = {
|
|
|
13956
14422
|
for (let i = 0; i < currentMarkAreaData.length; i++) {
|
|
13957
14423
|
const areaItem = currentMarkAreaData[i];
|
|
13958
14424
|
if (!areaItem.data || areaItem.data.length < 2) continue;
|
|
13959
|
-
if (lineInfo.laneId
|
|
14425
|
+
if (!this.isLaneSelected(lineInfo.laneId) && areaItem.type === "markArea")
|
|
13960
14426
|
continue;
|
|
13961
14427
|
const hasTimestamp = areaItem.data[0].timestamp;
|
|
13962
14428
|
const sortedData = hasTimestamp ? [...areaItem.data].sort(
|
|
@@ -14410,7 +14876,7 @@ const _sfc_main$2 = {
|
|
|
14410
14876
|
}
|
|
14411
14877
|
}
|
|
14412
14878
|
seriesIndex++;
|
|
14413
|
-
if (lineInfo.isUsed === "1" && this.isGeomechanical && lane.laneId
|
|
14879
|
+
if (lineInfo.isUsed === "1" && this.isGeomechanical && this.isLaneSelected(lane.laneId)) {
|
|
14414
14880
|
const boundaryPoints = this.findMissingDataBoundaryPoints(
|
|
14415
14881
|
this.plotSeries(seriesData, isLogScale)
|
|
14416
14882
|
);
|
|
@@ -14493,10 +14959,6 @@ const _sfc_main$2 = {
|
|
|
14493
14959
|
} finally {
|
|
14494
14960
|
this.isUpdatingChart = false;
|
|
14495
14961
|
this.scheduleConnectAllCharts();
|
|
14496
|
-
if (this.trendLineManager) {
|
|
14497
|
-
this.trendLineManager.scheduleZoomRender();
|
|
14498
|
-
this.$nextTick(() => this.trendLineManager.scheduleZoomRender());
|
|
14499
|
-
}
|
|
14500
14962
|
}
|
|
14501
14963
|
},
|
|
14502
14964
|
// 清空所有图表实例
|
|
@@ -14522,6 +14984,7 @@ const _sfc_main$2 = {
|
|
|
14522
14984
|
this.markAreaLineData = [];
|
|
14523
14985
|
this.laneSelectedPointPairs = {};
|
|
14524
14986
|
this.activeLaneId = null;
|
|
14987
|
+
this.activeLaneIds = [];
|
|
14525
14988
|
this.lineRange = {};
|
|
14526
14989
|
this.pendingRequestData = null;
|
|
14527
14990
|
this.initialRealTimeData = {};
|
|
@@ -15012,7 +15475,8 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
15012
15475
|
visibleData: $data.visibleData,
|
|
15013
15476
|
headerData: $data.headerData,
|
|
15014
15477
|
lineRange: $data.lineRange,
|
|
15015
|
-
activeLaneId: $data.activeLaneId
|
|
15478
|
+
activeLaneId: $data.activeLaneId,
|
|
15479
|
+
activeLaneIds: $data.activeLaneIds
|
|
15016
15480
|
}), createSlots({ _: 2 }, [
|
|
15017
15481
|
renderList($props.headerSlotName, (lane) => {
|
|
15018
15482
|
return {
|
|
@@ -15112,7 +15576,7 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
15112
15576
|
])
|
|
15113
15577
|
};
|
|
15114
15578
|
})
|
|
15115
|
-
]), 1040, ["onTemplateChange", "onLineChange", "onLaneWidthChange", "onParamsChange", "visibleData", "headerData", "lineRange", "activeLaneId"])
|
|
15579
|
+
]), 1040, ["onTemplateChange", "onLineChange", "onLaneWidthChange", "onParamsChange", "visibleData", "headerData", "lineRange", "activeLaneId", "activeLaneIds"])
|
|
15116
15580
|
], 512),
|
|
15117
15581
|
withDirectives(createElementVNode("div", _hoisted_2$2, null, 512), [
|
|
15118
15582
|
[vShow, $data.crosshairVisible]
|
|
@@ -15155,7 +15619,7 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
15155
15619
|
], 40, _hoisted_3$1)) : (openBlock(), createElementBlock("div", {
|
|
15156
15620
|
key: 1,
|
|
15157
15621
|
class: "context-menu-item",
|
|
15158
|
-
onClick: ($event) => $options.handleContextMenuItemClick(item)
|
|
15622
|
+
onClick: withModifiers(($event) => $options.handleContextMenuItemClick(item), ["stop"])
|
|
15159
15623
|
}, [
|
|
15160
15624
|
createElementVNode("span", null, toDisplayString(item.label), 1)
|
|
15161
15625
|
], 8, _hoisted_5))
|
|
@@ -15167,7 +15631,7 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
15167
15631
|
])
|
|
15168
15632
|
], 544);
|
|
15169
15633
|
}
|
|
15170
|
-
const chartContainer = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2], ["__scopeId", "data-v-
|
|
15634
|
+
const chartContainer = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2], ["__scopeId", "data-v-9a816c60"]]);
|
|
15171
15635
|
const _sfc_main$1 = {
|
|
15172
15636
|
name: "ParameterPanel",
|
|
15173
15637
|
props: {
|
|
@@ -16313,6 +16777,12 @@ const _sfc_main = {
|
|
|
16313
16777
|
this.$refs.chartContainer.resetAllTrendLines();
|
|
16314
16778
|
}
|
|
16315
16779
|
},
|
|
16780
|
+
// 退出编辑时清掉泳道选中。8.25
|
|
16781
|
+
clearActiveLane() {
|
|
16782
|
+
if (this.$refs.chartContainer && this.$refs.chartContainer.clearActiveLane) {
|
|
16783
|
+
this.$refs.chartContainer.clearActiveLane();
|
|
16784
|
+
}
|
|
16785
|
+
},
|
|
16316
16786
|
// 新增:更新form数据缓存
|
|
16317
16787
|
updateForm(content) {
|
|
16318
16788
|
let key = cloneDeep(content.key);
|
|
@@ -16682,7 +17152,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
16682
17152
|
])])) : createCommentVNode("", true)
|
|
16683
17153
|
]);
|
|
16684
17154
|
}
|
|
16685
|
-
const FrameLayoutComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-
|
|
17155
|
+
const FrameLayoutComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-51f78d28"]]);
|
|
16686
17156
|
KdLaneContainerComponent.install = function(app) {
|
|
16687
17157
|
app.component(KdLaneContainerComponent.name, KdLaneContainerComponent);
|
|
16688
17158
|
};
|