kd-lane-chart-v3 0.1.4 → 0.1.5

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 CHANGED
@@ -3790,6 +3790,7 @@ class TrendLineManager {
3790
3790
  this._zoomRaf = null;
3791
3791
  this._zoomPending = false;
3792
3792
  this._zoomEndTimer = null;
3793
+ this._graphicIds = /* @__PURE__ */ Object.create(null);
3793
3794
  this._ignoreClickUntil = 0;
3794
3795
  }
3795
3796
  destroy() {
@@ -3939,15 +3940,13 @@ class TrendLineManager {
3939
3940
  }
3940
3941
  }
3941
3942
  /** 图表重绘后对齐叠加层;拖拽中跳过,避免和 _onDragMove 抢 setOption。8.21 */
3943
+ // 只排一帧,不再连刷两次 renderAll(会闪)。8.24
3942
3944
  scheduleRender() {
3943
3945
  if (this.dragSession) return;
3944
3946
  if (this._raf) return;
3945
3947
  this._raf = requestAnimationFrame(() => {
3946
3948
  this._raf = null;
3947
3949
  this.renderAll();
3948
- requestAnimationFrame(() => {
3949
- if (!this.dragSession) this.renderAll();
3950
- });
3951
3950
  });
3952
3951
  }
3953
3952
  /** 缩放过程用 ZR 就地改像素,结束后再整层重画,避免 replaceMerge 把线冲掉。8.22 */
@@ -3994,7 +3993,7 @@ class TrendLineManager {
3994
3993
  patches.push(...this._buildPatches(chart, target));
3995
3994
  });
3996
3995
  if (!patches.length) return;
3997
- if (!this._applyPatchesViaZr(chart, patches)) {
3996
+ if (!this._applyPatchesViaZr(chart, patches) && !this._zoomPending) {
3998
3997
  this.renderLane(laneId);
3999
3998
  }
4000
3999
  }
@@ -4145,8 +4144,7 @@ class TrendLineManager {
4145
4144
  this.dragSession = null;
4146
4145
  this._setPanLocked(false, true);
4147
4146
  this._ignoreClickUntil = Date.now() + 300;
4148
- this.renderLane(sessionTarget.laneId);
4149
- this._emitChange(sessionTarget);
4147
+ this._emitChange(sessionTarget, { redraw: false });
4150
4148
  };
4151
4149
  el.__trendOnDown = onDown;
4152
4150
  el.__trendOnDrag = onDrag;
@@ -4170,12 +4168,32 @@ class TrendLineManager {
4170
4168
  }
4171
4169
  return applied > 0;
4172
4170
  }
4173
- renderAll() {
4171
+ // 只 merge 新图形,不动已有线。8.24
4172
+ _addGraphicElements(chart, elements) {
4173
+ if (!elements.length) return;
4174
+ chart.setOption(
4175
+ {
4176
+ graphic: elements.map((el) => ({ ...el, $action: "merge" }))
4177
+ },
4178
+ { silent: true, lazyUpdate: false }
4179
+ );
4180
+ }
4181
+ // 按 id 删除,不 replaceMerge 整层 graphic。8.24
4182
+ _removeGraphicIds(chart, ids) {
4183
+ if (!ids.length) return;
4184
+ chart.setOption(
4185
+ {
4186
+ graphic: ids.map((id) => ({ id, $action: "remove" }))
4187
+ },
4188
+ { silent: true, lazyUpdate: false }
4189
+ );
4190
+ }
4191
+ renderAll(forceReplace = false) {
4174
4192
  const lanes = this.host.currentTemplate && this.host.currentTemplate.lanes || [];
4175
- lanes.forEach((lane) => this.renderLane(lane.laneId));
4193
+ lanes.forEach((lane) => this.renderLane(lane.laneId, forceReplace));
4176
4194
  }
4177
- /** 用 graphic replaceMerge 整层替换,避免和图表其它 graphic 混在一起。8.21 */
4178
- renderLane(laneId) {
4195
+ /** 已有线只改 ZR 形状;新点/新线段单独 merge 进去,绝不整层 graphic 替换。8.24 */
4196
+ renderLane(laneId, forceReplace = false) {
4179
4197
  const chart = this.getChart(laneId);
4180
4198
  if (!chart) return;
4181
4199
  const targets = this.listDrawableTargets().filter((t) => t.laneId === laneId);
@@ -4185,12 +4203,28 @@ class TrendLineManager {
4185
4203
  });
4186
4204
  const hasKnots = targets.some((t) => (t.segments || []).some((s) => (s.knots || []).length));
4187
4205
  if (hasKnots && !elements.length) return;
4188
- chart.setOption(
4189
- { graphic: { elements } },
4190
- { replaceMerge: ["graphic"], lazyUpdate: false, silent: true }
4191
- );
4206
+ const nextIds = elements.map((el) => el.id);
4207
+ const prevIds = this._graphicIds[laneId] || [];
4208
+ const prevSet = new Set(prevIds);
4209
+ const nextSet = new Set(nextIds);
4210
+ const added = elements.filter((el) => !prevSet.has(el.id));
4211
+ const kept = elements.filter((el) => prevSet.has(el.id));
4212
+ const removedIds = prevIds.filter((id) => !nextSet.has(id));
4213
+ if (forceReplace) {
4214
+ this._removeGraphicIds(chart, prevIds);
4215
+ this._addGraphicElements(chart, elements);
4216
+ } else {
4217
+ if (kept.length) {
4218
+ this._applyPatchesViaZr(
4219
+ chart,
4220
+ kept.map((el) => ({ id: el.id, shape: el.shape }))
4221
+ );
4222
+ }
4223
+ if (removedIds.length) this._removeGraphicIds(chart, removedIds);
4224
+ if (added.length) this._addGraphicElements(chart, added);
4225
+ }
4226
+ this._graphicIds[laneId] = nextIds;
4192
4227
  this._bindPointInteractions(chart, laneId);
4193
- requestAnimationFrame(() => this._bindPointInteractions(chart, laneId));
4194
4228
  this.updateCursor(laneId);
4195
4229
  }
4196
4230
  _buildElements(chart, target) {
@@ -4444,7 +4478,7 @@ class TrendLineManager {
4444
4478
  }
4445
4479
  seg.knots = [...rest, knot].sort((a, b) => a.depth - b.depth);
4446
4480
  this.renderLane(target.laneId);
4447
- this._emitChange(target);
4481
+ this._emitChange(target, { redraw: false });
4448
4482
  }
4449
4483
  /** 取未关闭的最后一段;没有或已 _closed 则开新段。8.21 */
4450
4484
  _ensureActiveSegment(key) {
@@ -4488,7 +4522,7 @@ class TrendLineManager {
4488
4522
  const target = this.listDrawableTargets().find((t) => t.key === k);
4489
4523
  if (target) {
4490
4524
  this.renderLane(target.laneId);
4491
- this._emitChange(target);
4525
+ this._emitChange(target, { redraw: false });
4492
4526
  }
4493
4527
  return true;
4494
4528
  }
@@ -4507,15 +4541,15 @@ class TrendLineManager {
4507
4541
  segments: []
4508
4542
  });
4509
4543
  });
4510
- this.renderAll();
4544
+ this.renderAll(true);
4511
4545
  }
4512
4546
  /** 清空指定曲线的控制点;不传 key 则清当前编辑曲线。8.21 */
4513
4547
  resetTrendLine(key) {
4514
4548
  const target = key ? this.listDrawableTargets().find((t) => t.key === key) : this.getActiveTarget() || this.listDrawableTargets().find((t) => t.editable);
4515
4549
  if (!target) return;
4516
4550
  this.store[target.key] = { segments: [] };
4517
- this.renderLane(target.laneId);
4518
- this._emitChange(target);
4551
+ this.renderLane(target.laneId, true);
4552
+ this._emitChange(target, { redraw: false });
4519
4553
  }
4520
4554
  /** 删除一个控制点。段内只剩 0~1 个点时整段丢掉(画不出线)。8.21 */
4521
4555
  deleteKnot(payload) {
@@ -4533,8 +4567,8 @@ class TrendLineManager {
4533
4567
  }).filter((s) => s.knots.length > 0);
4534
4568
  const target = this.listDrawableTargets().find((t) => t.key === payload.key);
4535
4569
  const laneId = target && target.laneId || payload.laneId;
4536
- if (laneId) this.renderLane(laneId);
4537
- if (target) this._emitChange(target);
4570
+ if (laneId) this.renderLane(laneId, true);
4571
+ if (target) this._emitChange(target, { redraw: false });
4538
4572
  }
4539
4573
  /** 返回 geosteering trendLinePoint 格式的线段数组;8137 带上 isDouble / calcType。8.22 */
4540
4574
  getTrendLineData(mainId = "demo") {
@@ -4653,9 +4687,7 @@ class TrendLineManager {
4653
4687
  }
4654
4688
  this._ignoreClickUntil = Date.now() + 300;
4655
4689
  this.updateCursor(session.target.laneId);
4656
- this.renderLane(session.target.laneId);
4657
- if (emit) this._emitChange(session.target);
4658
- else this._scheduleRenderAfterVue();
4690
+ if (emit) this._emitChange(session.target, { redraw: false });
4659
4691
  }
4660
4692
  _clearClickTimer() {
4661
4693
  if (this.clickTimer) {
@@ -4664,25 +4696,23 @@ class TrendLineManager {
4664
4696
  }
4665
4697
  }
4666
4698
  /** 抛 trend-change(拖拽过程中不抛,只在松开时抛);不写回响应式模板。8.22 */
4667
- _emitChange(target) {
4699
+ // redraw=false:本地已画过,避免再 scheduleRender 把线闪掉。8.24
4700
+ _emitChange(target, { redraw = true } = {}) {
4668
4701
  const segments = cloneSegments(this.store[target.key] && this.store[target.key].segments || []);
4669
4702
  this.host.$emit("trend-change", {
4670
4703
  paramId: target.paramId,
4671
4704
  laneId: target.laneId,
4672
4705
  segments
4673
4706
  });
4674
- this._scheduleRenderAfterVue();
4707
+ if (redraw) this._scheduleRenderAfterVue();
4675
4708
  }
4676
4709
  /** 等 Vue / 图表 setOption 完成后再画叠加层。8.22 */
4710
+ // 只 nextTick 一次,不再叠 rAF 连刷。8.24
4677
4711
  _scheduleRenderAfterVue() {
4678
- const run = () => this.scheduleRender();
4679
4712
  if (this.host && typeof this.host.$nextTick === "function") {
4680
- this.host.$nextTick(() => {
4681
- run();
4682
- requestAnimationFrame(run);
4683
- });
4713
+ this.host.$nextTick(() => this.scheduleRender());
4684
4714
  } else {
4685
- requestAnimationFrame(run);
4715
+ this.scheduleRender();
4686
4716
  }
4687
4717
  }
4688
4718
  /** 手动填写不画镜像;模型计算或回显数据里已有 mirrorValue 则画第二条线。8.22 */
@@ -4867,7 +4897,7 @@ class TrendLineManager {
4867
4897
  }).filter((s) => s.knots.length > 0);
4868
4898
  this.renderLane(found.laneId);
4869
4899
  const target = this.listDrawableTargets().find((t) => t.key === key);
4870
- if (target) this._emitChange(target);
4900
+ if (target) this._emitChange(target, { redraw: false });
4871
4901
  }
4872
4902
  /** 模型计算抽屉确定:写入岩性/偏移并生成镜像值。8.22 */
4873
4903
  applyMoxingConfig(paramId, form) {
@@ -4938,7 +4968,7 @@ class TrendLineManager {
4938
4968
  seg.knots = [...rest, knot].sort((a, b) => a.depth - b.depth);
4939
4969
  this.renderLane(found.laneId);
4940
4970
  const target = this.listDrawableTargets().find((t) => t.key === key);
4941
- if (target) this._emitChange(target);
4971
+ if (target) this._emitChange(target, { redraw: false });
4942
4972
  }
4943
4973
  }
4944
4974
  const _sfc_main$6 = {
@@ -6332,6 +6362,8 @@ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
6332
6362
  group: { name: "laneGroup", pull: false, put: false },
6333
6363
  "item-key": "laneId",
6334
6364
  filter: $options.laneDragFilter,
6365
+ "prevent-on-filter": false,
6366
+ handle: $props.isGeomechanical ? ".kd-lane-chart-lane-header" : void 0,
6335
6367
  axis: "x"
6336
6368
  }, {
6337
6369
  default: withCtx(() => [
@@ -6436,7 +6468,7 @@ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
6436
6468
  }), 128))
6437
6469
  ]),
6438
6470
  _: 3
6439
- }, 8, ["onStart", "onEnd", "modelValue", "filter"])
6471
+ }, 8, ["onStart", "onEnd", "modelValue", "filter", "handle"])
6440
6472
  ], 64)) : (openBlock(), createElementBlock("div", _hoisted_13$1, [
6441
6473
  createElementVNode("div", {
6442
6474
  class: normalizeClass(["kd-lane-chart-lane-header", { "kd-lane-chart-lane-header-isKdCurveV2": $props.isKdCurveV2 }]),
@@ -6518,7 +6550,7 @@ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
6518
6550
  }, 8, ["modelValue", "onClose"])
6519
6551
  ], 544);
6520
6552
  }
6521
- const KdLaneContainerComponent = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6], ["__scopeId", "data-v-4f706753"]]);
6553
+ const KdLaneContainerComponent = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6], ["__scopeId", "data-v-afde8956"]]);
6522
6554
  const SLIDER_GROUP_ID = "depthSliderGroup";
6523
6555
  function pad2(n) {
6524
6556
  return n < 10 ? "0" + n : "" + n;
@@ -9104,24 +9136,53 @@ const _sfc_main$3 = {
9104
9136
  }
9105
9137
  return null;
9106
9138
  },
9107
- _restoreDataZoomState(savedState) {
9108
- if (!savedState || !this.chart || this.chart.isDisposed()) return;
9139
+ // notMerge 刷 option 时把当前趋势线 graphic 带回去,避免先消失再画。8.24
9140
+ _preserveGraphic(options) {
9141
+ if (!options || options.graphic || !this.chart || this.chart.isDisposed()) return;
9109
9142
  try {
9110
- const currentOption = this.chart.getOption();
9111
- if (!currentOption.dataZoom || currentOption.dataZoom.length === 0) return;
9112
- savedState.forEach((state, i) => {
9113
- if (i < currentOption.dataZoom.length) {
9114
- const dz = currentOption.dataZoom[i];
9115
- if (state.start !== void 0) dz.start = state.start;
9116
- if (state.end !== void 0) dz.end = state.end;
9117
- if (state.startValue !== void 0) dz.startValue = state.startValue;
9118
- if (state.endValue !== void 0) dz.endValue = state.endValue;
9119
- }
9120
- });
9121
- this.chart.setOption({ dataZoom: currentOption.dataZoom });
9143
+ const current = this.chart.getOption();
9144
+ if (current && current.graphic && current.graphic.length) {
9145
+ options.graphic = current.graphic;
9146
+ }
9122
9147
  } catch (e) {
9123
9148
  }
9124
9149
  },
9150
+ // dataZoom 写进即将下发的 option,不再二次 setOption 打断 Chrome 平移。8.24
9151
+ _applySavedDataZoomToOptions(options, savedState) {
9152
+ if (!savedState || !options) return;
9153
+ const raw = options.dataZoom;
9154
+ if (!raw) return;
9155
+ const list = Array.isArray(raw) ? raw : [raw];
9156
+ savedState.forEach((state, i) => {
9157
+ if (!list[i] || !state) return;
9158
+ if (state.start !== void 0) list[i].start = state.start;
9159
+ if (state.end !== void 0) list[i].end = state.end;
9160
+ if (state.startValue !== void 0) list[i].startValue = state.startValue;
9161
+ if (state.endValue !== void 0) list[i].endValue = state.endValue;
9162
+ });
9163
+ },
9164
+ // 拦截 HTML5 dragstart,Chrome 才能把 mousemove 交给 dataZoom。8.24
9165
+ _preventNativeDrag(e) {
9166
+ e.preventDefault();
9167
+ },
9168
+ _bindNativeDragGuard() {
9169
+ const el = this.$el;
9170
+ if (!el || el.__kdNativeDragBound) return;
9171
+ el.__kdNativeDragBound = true;
9172
+ el.setAttribute("draggable", "false");
9173
+ el.addEventListener("dragstart", this._preventNativeDrag, true);
9174
+ const canvases = el.querySelectorAll("canvas");
9175
+ canvases.forEach((canvas) => {
9176
+ canvas.draggable = false;
9177
+ canvas.setAttribute("draggable", "false");
9178
+ });
9179
+ },
9180
+ _unbindNativeDragGuard() {
9181
+ const el = this.$el;
9182
+ if (!el) return;
9183
+ el.removeEventListener("dragstart", this._preventNativeDrag, true);
9184
+ el.__kdNativeDragBound = false;
9185
+ },
9125
9186
  // provide an explicit merge option method
9126
9187
  mergeOptions(options, notMerge, lazyUpdate, skipClone) {
9127
9188
  if (this.manualUpdate) {
@@ -9132,10 +9193,10 @@ const _sfc_main$3 = {
9132
9193
  } else {
9133
9194
  this._skipWatcher = true;
9134
9195
  const savedDataZoom = this._saveDataZoomState();
9135
- this.delegateMethod("setOption", this.getOptionsWithTheme(options, skipClone), notMerge, lazyUpdate);
9136
- if (savedDataZoom) {
9137
- this._restoreDataZoomState(savedDataZoom);
9138
- }
9196
+ const next = this.getOptionsWithTheme(options, skipClone);
9197
+ this._applySavedDataZoomToOptions(next, savedDataZoom);
9198
+ this._preserveGraphic(next);
9199
+ this.delegateMethod("setOption", next, notMerge, lazyUpdate);
9139
9200
  this.$nextTick(() => {
9140
9201
  this._skipWatcher = false;
9141
9202
  });
@@ -9215,6 +9276,7 @@ const _sfc_main$3 = {
9215
9276
  chart.group = this.group;
9216
9277
  }
9217
9278
  chart.setOption(this.getOptionsWithTheme(options || this.manualOptions || this.options || {}), true);
9279
+ this._bindNativeDragGuard();
9218
9280
  Object.keys(this.$attrs).forEach((key) => {
9219
9281
  if (!key.startsWith("on") || typeof this.$attrs[key] !== "function") {
9220
9282
  return;
@@ -9294,10 +9356,10 @@ const _sfc_main$3 = {
9294
9356
  this.init(val);
9295
9357
  } else {
9296
9358
  const savedDataZoom = this._saveDataZoomState();
9297
- this.chart.setOption(this.getOptionsWithTheme(val), val !== oldVal);
9298
- if (savedDataZoom) {
9299
- this._restoreDataZoomState(savedDataZoom);
9300
- }
9359
+ const next = this.getOptionsWithTheme(val);
9360
+ this._applySavedDataZoomToOptions(next, savedDataZoom);
9361
+ this._preserveGraphic(next);
9362
+ this.chart.setOption(next, val !== oldVal);
9301
9363
  if (this.group) {
9302
9364
  this.chart.group = this.group;
9303
9365
  }
@@ -9308,6 +9370,7 @@ const _sfc_main$3 = {
9308
9370
  }
9309
9371
  },
9310
9372
  destroy() {
9373
+ this._unbindNativeDragGuard();
9311
9374
  if (this.autoresize) {
9312
9375
  removeListener(this.$el, this.__resizeHandler);
9313
9376
  }
@@ -9382,7 +9445,7 @@ const _hoisted_1$3 = { class: "echarts" };
9382
9445
  function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
9383
9446
  return openBlock(), createElementBlock("div", _hoisted_1$3);
9384
9447
  }
9385
- const resizeEcharts = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3], ["__scopeId", "data-v-de2449c9"]]);
9448
+ const resizeEcharts = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3], ["__scopeId", "data-v-0df7a705"]]);
9386
9449
  const DRAW_POINT_MIN = 600;
9387
9450
  const DRAW_POINT_MAX = 1800;
9388
9451
  function getSeriesDrawThreshold(laneHeightPx) {
@@ -10645,12 +10708,10 @@ const _sfc_main$2 = {
10645
10708
  this.visibleData = markRaw(this.realTimeData.slice(startIndex, end));
10646
10709
  return this.visibleData;
10647
10710
  },
10648
- /** 地应力:进图用全量行,不按窗口截断。8.24 */
10711
+ /** 进图只吃当前窗口。地应力也不准喂整口井,否则井深轴会拉成全井量程。8.24 */
10649
10712
  getChartDrawRows(transferData) {
10650
10713
  if (transferData && transferData.length > 0) return transferData;
10651
- this.getVisibleData();
10652
- if (this.isGeomechanical) return this.realTimeData || [];
10653
- return this.visibleData;
10714
+ return this.getVisibleData();
10654
10715
  },
10655
10716
  getRowsAxisExtent(rows, key) {
10656
10717
  let min = Infinity;
@@ -14336,7 +14397,7 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
14336
14397
  ])
14337
14398
  ], 544);
14338
14399
  }
14339
- const chartContainer = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2], ["__scopeId", "data-v-f4dde916"]]);
14400
+ const chartContainer = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2], ["__scopeId", "data-v-5da40120"]]);
14340
14401
  const _sfc_main$1 = {
14341
14402
  name: "ParameterPanel",
14342
14403
  props: {