@publishfx/publish-chart 2.1.13 → 2.1.15

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.
@@ -61,7 +61,6 @@ function applyAxisX(mark, options = {}) {
61
61
  const needSampling = dataCount > 0 && containerWidth > 0;
62
62
  const interval = needSampling ? calcAxisInterval(dataCount, containerWidth, maxLabelChars, fontSize) : 1;
63
63
  const axisFilter = needSampling && interval > 1 ? (type)=>createAxisFilter(type, interval, dataCount) : null;
64
- console.log('axisFilter:', interval);
65
64
  mark.axis('x', {
66
65
  title,
67
66
  grid,
@@ -82,6 +81,12 @@ function applyAxisX(mark, options = {}) {
82
81
  },
83
82
  labelAlign: 'horizontal',
84
83
  labelDx: (_datum, _index, _data)=>0,
84
+ labelRender: (datum)=>{
85
+ let left = '0%';
86
+ if (datum.value > 0.9) left = '-13%';
87
+ else if (datum.value < 0.1) left = '10%';
88
+ return `<div style="transform: translateX(${left});">${datum.label}</div>`;
89
+ },
85
90
  labelOpacity: 0.6,
86
91
  ...axisFilter && {
87
92
  tickFilter: axisFilter('tick'),
@@ -148,22 +153,16 @@ function applyLegendColor(view, options = {}) {
148
153
  }
149
154
  function applyAuxiliaryLineY(view, lines, options = {}) {
150
155
  if (!lines?.length) return;
151
- console.log('applyAuxiliaryLineY:', lines);
152
156
  const { stroke = '#F4664A', strokeOpacity = 1, labelMaxLength = 5 } = options;
153
157
  lines.forEach((auxLine)=>{
154
- console.log('lines:', auxLine);
155
- view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').scale('y', {
158
+ view.lineY().encode('y', auxLine.value).style('stroke', stroke).style('strokeOpacity', strokeOpacity).style('lineWidth', 1).style('shadowColor', 'transparent').animate(false).scale('y', {
156
159
  key: auxLine?.axis === 'right' ? 'line' : 'main'
157
160
  }).axis('x', false).label({
158
161
  dx: 0,
159
162
  dy: 0,
160
- text: splitTextToMultiline(auxLine.name, labelMaxLength, '\n'),
163
+ text: splitTextToMultiline(auxLine.name, labelMaxLength, '<br />'),
161
164
  position: auxLine?.axis === 'right' ? 'bottom-right' : 'bottom-left',
162
- style: {
163
- fill: stroke,
164
- shadowColor: 'transparent',
165
- fillOpacity: 1
166
- }
165
+ render: (text)=>`<div style="background-color: transparent; padding: 5px; border-radius: 5px;font-size: 14px;position: absolute;left: ${auxLine?.axis === 'right' ? '-105px' : '0px'}; top: -24px; width: 100px;color: ${stroke}; font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;">${text}</div>`
167
166
  });
168
167
  });
169
168
  }
@@ -181,35 +180,23 @@ function applyHighlightDate(view, x, data, highlightDate, isHighlight) {
181
180
  [x]: item,
182
181
  ['highlight']: highlightDate.includes(item) ? 100 : 0
183
182
  }));
184
- const highlightInterval = view.interval().data(highlightData).encode('x', x).encode('y', 'highlight').scale('y', {
183
+ const highlightInterval = view.interval().data(highlightData).encode('x', x).encode('y', 'highlight').animate(false).scale('y', {
185
184
  type: 'linear',
186
185
  domainMin: 0,
187
186
  domainMax: 100,
188
187
  independent: true
189
- }).tooltip(false).axis('y', {
190
- position: 'top',
191
- title: false,
192
- grid: false,
193
- label: false,
194
- tick: false
195
- });
188
+ }).tooltip(false).axis('y', false);
196
189
  highlightInterval.style({
197
190
  columnWidthRatio: 0.6,
198
191
  fill: '#cccccc',
199
192
  fillOpacity: isHighlight ? 0.3 : 0
200
193
  });
201
- view.line().data(highlightData).encode('x', x).encode('y', 'highlight').scale('y', {
194
+ view.line().data(highlightData).encode('x', x).encode('y', 'highlight').animate(false).scale('y', {
202
195
  type: 'linear',
203
196
  domainMin: 0,
204
197
  domainMax: 100,
205
198
  independent: true
206
- }).tooltip(true).axis('y', {
207
- position: 'top',
208
- title: false,
209
- grid: false,
210
- label: false,
211
- tick: false
212
- }).style({
199
+ }).tooltip(true).axis('y', false).style({
213
200
  stroke: 'transparent',
214
201
  strokeOpacity: 1
215
202
  });
@@ -242,7 +229,7 @@ function applyNodeData(view, nodeData, x, y) {
242
229
  const c1 = document.createElement('circle', {
243
230
  style: {
244
231
  cx: px,
245
- cy: py,
232
+ cy: py + 3,
246
233
  r: 2,
247
234
  fill: 'white'
248
235
  }
@@ -250,7 +237,7 @@ function applyNodeData(view, nodeData, x, y) {
250
237
  const c2 = document.createElement('circle', {
251
238
  style: {
252
239
  cx: px,
253
- cy: py,
240
+ cy: py + 3,
254
241
  r: 5,
255
242
  fill: item.color
256
243
  }
@@ -275,4 +262,58 @@ const sortByIndicators = (arr, indicators)=>arr.sort((a, b)=>{
275
262
  if (-1 !== indexA && -1 !== indexB) return indexA - indexB;
276
263
  return 0;
277
264
  });
278
- export { adjustDomainMax, applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyNodeData, applyScaleYLinear, createChart, getColorByGroupType, getMainView, sortByIndicators };
265
+ function intervalSort(a, b) {
266
+ const itemRank = (item)=>{
267
+ if (item.isChange) return 2;
268
+ if (item.name.includes('_compare')) return 1;
269
+ return 0;
270
+ };
271
+ return itemRank(a) - itemRank(b);
272
+ }
273
+ function fillMissingIndicator(baseItems, safeTitle, isCompare, isGroup = false) {
274
+ const indicatorIds = baseItems.filter((item)=>item.indicatorId).map((item)=>item.indicatorId);
275
+ const indicatorIdSet = new Map(indicatorIds.map((id)=>[
276
+ id,
277
+ 0
278
+ ]));
279
+ if (isCompare && !isGroup) {
280
+ baseItems.forEach((item)=>{
281
+ if (item.indicatorId) indicatorIdSet.set(item.indicatorId, (indicatorIdSet.get(item.indicatorId) ?? 0) + 1);
282
+ });
283
+ indicatorIdSet.forEach((count, indicatorId)=>{
284
+ if (3 !== count) {
285
+ const color = baseItems.filter((item)=>'transparent' !== item.color).map((item)=>item.color)[0];
286
+ if (!baseItems.find((item)=>item.indicatorId === indicatorId && item.name === indicatorId)) baseItems.push({
287
+ indicatorId: indicatorId,
288
+ name: indicatorId,
289
+ value: '-',
290
+ x: safeTitle,
291
+ color: color
292
+ });
293
+ if (!baseItems.find((item)=>item.indicatorId === indicatorId && item.name === indicatorId + '_compare')) baseItems.push({
294
+ indicatorId: indicatorId,
295
+ name: indicatorId + '_compare',
296
+ tipType: 'compareline',
297
+ value: '-',
298
+ x: safeTitle
299
+ });
300
+ if (!baseItems.find((item)=>item.indicatorId === indicatorId && item.name === indicatorId + '_change')) baseItems.push({
301
+ indicatorId: indicatorId,
302
+ name: indicatorId + '_change',
303
+ isChange: true,
304
+ value: '-',
305
+ x: safeTitle
306
+ });
307
+ }
308
+ });
309
+ }
310
+ const safeItems = baseItems.map((item)=>{
311
+ if (item.x !== safeTitle) return {
312
+ ...item,
313
+ value: '-'
314
+ };
315
+ return item;
316
+ }).sort(intervalSort);
317
+ return safeItems;
318
+ }
319
+ export { adjustDomainMax, applyAuxiliaryLineY, applyAxisX, applyAxisY, applyHighlightDate, applyLegendColor, applyNodeData, applyScaleYLinear, createChart, fillMissingIndicator, getColorByGroupType, getMainView, intervalSort, sortByIndicators };
@@ -20,7 +20,6 @@ function renderG2BarChart(container, options) {
20
20
  paddingBottom: 0,
21
21
  insetBottom: 0
22
22
  });
23
- console.log('isLegend:', legend, isLegend);
24
23
  const view = getMainView(chart);
25
24
  view.attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', isLegend ? 0 : 16);
26
25
  if (isHorizontal) view.coordinate({
@@ -37,11 +36,10 @@ function renderG2BarChart(container, options) {
37
36
  key: 'main'
38
37
  });
39
38
  if (!CLOSE_HIGHLIGHT_DEBUG) applyHighlightDate(view, x, data, highlightDate, isHighlight);
40
- console.log('g2bar data:', data, y);
41
39
  const interval = view.interval().encode('x', x).encode('y', y).encode('color', 'groupType').transform({
42
40
  type: 'dodgeX',
43
41
  padding: isHorizontal ? 0.2 : 0
44
- });
42
+ }).animate(false);
45
43
  interval.style({
46
44
  columnWidthRatio: 0.6,
47
45
  insetLeft: (_d, index, _data, _column)=>{
@@ -145,7 +143,6 @@ function renderG2BarChart(container, options) {
145
143
  bounding: tooltipBounding
146
144
  });
147
145
  applyAuxiliaryLineY(view, auxiliaryLineData);
148
- console.log('nodeList data:', data);
149
146
  if (!CLOSE_NODE_DEBUG) {
150
147
  const nodeList = applyNodeData(view, nodeData, x, y);
151
148
  onNodeListChange?.(nodeList);
@@ -170,7 +167,6 @@ function renderG2BarChart(container, options) {
170
167
  let hasEmittedNodeList = false;
171
168
  chart.on('afterrender', (_e)=>{
172
169
  if (hasEmittedNodeList) return;
173
- console.log('chart.coordinateBBox:', chart.getContext(), view.getCoordinate());
174
170
  const views = chart.getContext()?.views;
175
171
  const viewCoordinate = views?.[0]?.layout;
176
172
  if (onChartRender && viewCoordinate) onChartRender({
@@ -18,6 +18,10 @@ export interface RenderG2CombineChartOptions {
18
18
  z: string;
19
19
  /** 柱状图 Y 轴最大值 */
20
20
  maxY: number;
21
+ /** 柱状图 Y 轴最大值 */
22
+ maxLeft: number;
23
+ /** 折线图 Y 轴最大值 */
24
+ maxRight: number;
21
25
  /** 高亮日期,用于 x 轴 gridFilter */
22
26
  highlightDate?: string[];
23
27
  /** 主题色数组 */
@@ -1,11 +1,11 @@
1
1
  import { lines } from "@antv/g-pattern";
2
- import { applyAuxiliaryLineY, applyAxisX, applyHighlightDate, applyNodeData, applyScaleYLinear, createChart, getMainView } from "./g2Helpers.js";
2
+ import { applyAuxiliaryLineY, applyAxisX, applyHighlightDate, applyNodeData, applyScaleYLinear, createChart, fillMissingIndicator, getMainView } from "./g2Helpers.js";
3
3
  import { getIndicatorCompareName } from "../../../utils/indicatorHelpers.js";
4
4
  const Y_AXIS_FIELD = 'groupValue';
5
5
  const BAR_Y_FIELD = 'barValue';
6
6
  const LINE_Y_FIELD = 'lineValue';
7
7
  function renderG2CombineChart(container, options) {
8
- const { data, nodeData, x, y, z: _z, maxY, themeColors, indicatorMap: _indicatorMap, formatAxis, formatLineAxis, isDataTag = true, isCombineDataTag = true, isLegend: _isLegend = false, isCompare = false, formatLabel, highlightDate = [], height = 300, isHighlight = true, isClickable = false, indicators = [], tooltipRender, auxiliaryLineData = [], onNodeListChange, lineColors, onChartRender, isGroup, legendItems = [], indicatorId, isTooltipContent = false } = options;
8
+ const { data, nodeData, x, z: _z, maxLeft, maxRight, themeColors, indicatorMap: _indicatorMap, formatAxis, formatLineAxis, isDataTag = true, isCombineDataTag = true, isLegend: _isLegend = false, isCompare = false, formatLabel, highlightDate = [], height = 300, isHighlight = true, isClickable = false, indicators = [], tooltipRender, auxiliaryLineData = [], onNodeListChange, lineColors, onChartRender, isGroup, legendItems = [], indicatorId, isTooltipContent = false } = options;
9
9
  const chart = createChart({
10
10
  container,
11
11
  height,
@@ -14,11 +14,11 @@ function renderG2CombineChart(container, options) {
14
14
  chart.options({
15
15
  marginBottom: 0,
16
16
  paddingBottom: 0,
17
- insetBottom: 0
17
+ insetBottom: 0,
18
+ animate: null
18
19
  });
19
20
  const view = getMainView(chart);
20
- view.attr('insetLeft', 0).attr('insetRight', 0).attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', 0);
21
- console.log('renderG2CombineChart data:', data, 'maxY:', maxY, x, y, 'indicators:', indicators);
21
+ view.attr('insetLeft', 0).attr('insetRight', 0).attr('marginLeft', 0).attr('marginRight', 0).attr('marginBottom', 0).attr('animate', false).animate(false);
22
22
  view.data(data);
23
23
  const xValueCount = new Set(data.map((d)=>d[x])).size;
24
24
  applyAxisX(view, {
@@ -28,27 +28,17 @@ function renderG2CombineChart(container, options) {
28
28
  containerWidth: container.clientWidth
29
29
  });
30
30
  const barColor = themeColors[0] ?? "#5B8FF9";
31
- console.log('tooltip: themeColors:', themeColors[0], barColor, isGroup);
32
- console.log('renderG2CombineChart highlightDate:', highlightDate, isHighlight);
33
31
  applyHighlightDate(view, x, data, highlightDate, isHighlight);
34
32
  const intervalData = data.filter((item)=>!item.isCombine).map((item)=>({
35
33
  ...item,
36
34
  [BAR_Y_FIELD]: item[Y_AXIS_FIELD]
37
35
  }));
38
- console.log('renderG2CombineChart interval data:', intervalData);
39
- const intervalMaxY = intervalData.reduce((max, item)=>{
40
- const key = isGroup ? "total" : BAR_Y_FIELD;
41
- console.log('tdv item:', key, item[key], intervalData);
42
- if ('-' === item[key] || void 0 === item[key] || null === item[key] || '' === item[key]) return max;
43
- return Math.max(max, item[key]);
44
- }, 0);
45
- console.log('tdv:', intervalMaxY);
46
36
  const auxLeftValues = auxiliaryLineData?.length ? auxiliaryLineData.filter((item)=>'left' === item.axis).map((item)=>item.value) : [];
47
37
  const maxAuxLeft = auxLeftValues.length ? Math.max(...auxLeftValues) : 0;
48
38
  const auxRightValues = auxiliaryLineData?.length ? auxiliaryLineData.filter((item)=>'right' === item.axis).map((item)=>item.value) : [];
49
39
  const maxAuxRight = auxRightValues.length ? Math.max(...auxRightValues) : 0;
50
- const finalIntervalMax = Math.max(intervalMaxY, maxAuxLeft);
51
- const interval = view.interval().data(intervalData).encode("x", x).encode("y", BAR_Y_FIELD).encode("color", "groupType").transform(isGroup ? {
40
+ const finalIntervalMax = Math.max(maxLeft, maxAuxLeft);
41
+ const interval = view.interval().data(intervalData).encode("x", x).encode("y", BAR_Y_FIELD).encode("color", "groupType").animate(false).transform(isGroup ? {
52
42
  type: 'stackY',
53
43
  reverse: true
54
44
  } : {
@@ -57,7 +47,6 @@ function renderG2CombineChart(container, options) {
57
47
  }).style({
58
48
  columnWidthRatio: 0.6,
59
49
  insetLeft: (_d, index, _data, _column)=>{
60
- console.log('insetLeft:', index, isCompare);
61
50
  if (isGroup) return 0;
62
51
  if (isCompare) return index % 2 === 0 ? 0 : 0;
63
52
  return 0;
@@ -110,13 +99,11 @@ function renderG2CombineChart(container, options) {
110
99
  labelFormatter: formatAxis,
111
100
  labelOpacity: 0.6
112
101
  });
113
- console.log('tooltip:', barColor, isCompare);
114
102
  interval.tooltip({
115
103
  items: isGroup ? [
116
104
  (datum)=>{
117
105
  const groupType = String(datum.groupType ?? '');
118
106
  const index = legendItems.findIndex((item)=>item.id === `${groupType}_${datum.isCombine}`);
119
- console.log(datum);
120
107
  return {
121
108
  value: datum[Y_AXIS_FIELD],
122
109
  name: datum['groupType'],
@@ -163,24 +150,12 @@ function renderG2CombineChart(container, options) {
163
150
  ...item,
164
151
  [LINE_Y_FIELD]: item[Y_AXIS_FIELD]
165
152
  }));
166
- console.log('renderG2CombineChart: line data:', data);
167
153
  const compareLineData = data.filter((item)=>item.isCombine && item.groupType.includes('_compare')).filter((item)=>'' !== item[Y_AXIS_FIELD]).map((item)=>({
168
154
  ...item,
169
155
  [LINE_Y_FIELD]: item[Y_AXIS_FIELD]
170
156
  }));
171
- console.log('compareLineData:', compareLineData);
172
- const lineMaxY = lineData.reduce((max, item)=>{
173
- if ('-' === item[LINE_Y_FIELD] || void 0 === item[LINE_Y_FIELD] || null === item[LINE_Y_FIELD] || '' === item[LINE_Y_FIELD]) return max;
174
- return Math.max(max, item[LINE_Y_FIELD]);
175
- }, 0);
176
- const compareLineMaxY = compareLineData.reduce((max, item)=>{
177
- if ('-' === item[LINE_Y_FIELD] || void 0 === item[LINE_Y_FIELD] || null === item[LINE_Y_FIELD] || '' === item[LINE_Y_FIELD]) return max;
178
- return Math.max(max, item[LINE_Y_FIELD]);
179
- }, 0);
180
- const lineFinalMaxY = Math.max(lineMaxY, compareLineMaxY) || 1;
181
- const finalLineMax = Math.max(lineFinalMaxY, maxAuxRight);
182
- console.log('lineData:', lineData);
183
- const line = view.line().data(lineData).encode("x", x).encode("y", LINE_Y_FIELD).encode('color', 'groupType').style({
157
+ const finalLineMax = Math.max(maxRight, maxAuxRight);
158
+ const line = view.line().data(lineData).encode("x", x).encode("y", LINE_Y_FIELD).encode('color', 'groupType').animate(false).style({
184
159
  lineWidth: 2,
185
160
  stroke: (datum)=>{
186
161
  const currentDatum = datum[0];
@@ -218,7 +193,7 @@ function renderG2CombineChart(container, options) {
218
193
  position: 'right',
219
194
  title: false,
220
195
  grid: true,
221
- gridStrokeOpacity: 0 === intervalMaxY ? 0.2 : 0,
196
+ gridStrokeOpacity: 0 === maxAuxLeft ? 0.2 : 0,
222
197
  gridLineWidth: 1,
223
198
  gridLineDash: [
224
199
  0,
@@ -228,8 +203,7 @@ function renderG2CombineChart(container, options) {
228
203
  labelFormatter: formatLineAxis,
229
204
  labelOpacity: 0.6
230
205
  });
231
- console.log('renderG2CombineChart: compare line data:', compareLineData);
232
- const compareLine = view.line().data(compareLineData).encode('x', x).encode('y', LINE_Y_FIELD).encode('color', 'groupType').style({
206
+ const compareLine = view.line().data(compareLineData).encode('x', x).encode('y', LINE_Y_FIELD).encode('color', 'groupType').animate(false).style({
233
207
  lineDash: [
234
208
  4,
235
209
  4
@@ -255,7 +229,6 @@ function renderG2CombineChart(container, options) {
255
229
  });
256
230
  compareLine.axis('y', false);
257
231
  const hasCompareData = data.some((item)=>item.groupType.includes('_compare'));
258
- console.log('hasCompareData:', hasCompareData, data);
259
232
  if (hasCompareData) compareLine.tooltip({
260
233
  items: [
261
234
  (datum)=>datum.groupType.includes('_compare') ? {
@@ -264,7 +237,7 @@ function renderG2CombineChart(container, options) {
264
237
  name: datum['groupType'],
265
238
  indicatorId: datum['groupType'].replace('_compare', ''),
266
239
  channel: Y_AXIS_FIELD,
267
- color: lineColors[indicators.slice(1).indexOf(String(datum['groupType'])) ?? 0] || 'transparent',
240
+ color: lineColors[indicators.slice(1).indexOf(String(datum['groupType']).replace('_compare', '')) ?? 0] || 'trans1parent',
268
241
  isCombine: true,
269
242
  tipType: 'compareline',
270
243
  x: datum[x]
@@ -281,149 +254,130 @@ function renderG2CombineChart(container, options) {
281
254
  } : false
282
255
  ].filter(Boolean)
283
256
  });
284
- if (tooltipRender) {
285
- const intervalSort = (item)=>{
286
- if (item.isChange) return 2;
287
- if (item.name.includes('_compare')) return 1;
288
- return 0;
289
- };
290
- view.interaction('tooltip', {
291
- shared: true,
292
- crosshairsY: true,
293
- marker: false,
294
- ...isTooltipContent ? {
295
- mount: 'body'
296
- } : {},
297
- render: (event, payload)=>{
298
- const { title, items } = payload;
299
- let safeTitle = title.replace(/,.*$/, '');
300
- const baseItems = items.filter((item)=>!item.isCombine);
301
- const safeItems = baseItems.map((item)=>{
302
- if (item.x !== safeTitle) return {
303
- ...item,
304
- value: '-'
305
- };
306
- return item;
307
- }).sort(intervalSort);
308
- const combineItems = items.filter((item)=>item.isCombine);
309
- const safeCombineItems = combineItems.map((item)=>{
310
- if (item.x !== safeTitle) return {
311
- ...item,
312
- value: '-'
313
- };
314
- return item;
315
- });
316
- const indicatorOrder = new Map(indicators.map((id, i)=>[
317
- id,
318
- i
319
- ]));
320
- const sortedCombineItems = [
321
- ...safeCombineItems
322
- ].sort((a, b)=>{
323
- const orderA = indicatorOrder.get(a.indicatorId) ?? 1 / 0;
324
- const orderB = indicatorOrder.get(b.indicatorId) ?? 1 / 0;
325
- if (orderA !== orderB) return orderA - orderB;
326
- const typeRank = (item)=>{
327
- if (item.isChange) return 2;
328
- if ('compareline' === item.tipType) return 1;
329
- return 0;
330
- };
331
- return typeRank(a) - typeRank(b);
332
- });
333
- const content = tooltipRender(safeTitle, [
334
- ...safeItems,
335
- ...sortedCombineItems
336
- ]) ?? null;
337
- if (content && isTooltipContent) {
338
- const domEvent = event?.event ?? event;
339
- const canvas = container.querySelector('canvas');
340
- const canvasRect = canvas ? canvas.getBoundingClientRect() : container.getBoundingClientRect();
341
- const canvasX = domEvent?.canvasX ?? domEvent?.x ?? 0;
342
- const canvasY = domEvent?.canvasY ?? domEvent?.y ?? 0;
343
- const clientX = canvasRect.left + canvasX;
344
- const clientY = canvasRect.top + canvasY;
345
- const offsetX = 12;
346
- const offsetY = 12;
347
- const applyPosition = ()=>{
348
- let el = content;
349
- while(el && el.parentElement){
350
- const p = el.parentElement;
351
- if (p.classList?.contains('g2-tooltip')) {
352
- el = p;
353
- break;
354
- }
257
+ if (tooltipRender) view.interaction('tooltip', {
258
+ shared: true,
259
+ crosshairsY: true,
260
+ marker: false,
261
+ ...isTooltipContent ? {
262
+ mount: 'body'
263
+ } : {},
264
+ render: (event, payload)=>{
265
+ const { title, items } = payload;
266
+ let safeTitle = title.replace(/,.*$/, '');
267
+ const baseItems = items.filter((item)=>item.hasOwnProperty('isCombine') && !item.isCombine);
268
+ const safeItems = fillMissingIndicator(baseItems, safeTitle, isCompare, isGroup);
269
+ const combineItems = items.filter((item)=>item.hasOwnProperty('isCombine') && item.isCombine);
270
+ const safeCombineItems = fillMissingIndicator(combineItems, safeTitle, isCompare, isGroup);
271
+ const indicatorOrder = new Map(indicators.map((id, i)=>[
272
+ id,
273
+ i
274
+ ]));
275
+ const sortedCombineItems = [
276
+ ...safeCombineItems
277
+ ].sort((a, b)=>{
278
+ const orderA = indicatorOrder.get(a.indicatorId) ?? 1 / 0;
279
+ const orderB = indicatorOrder.get(b.indicatorId) ?? 1 / 0;
280
+ if (orderA !== orderB) return orderA - orderB;
281
+ const typeRank = (item)=>{
282
+ if (item.isChange) return 2;
283
+ if ('compareline' === item.tipType) return 1;
284
+ return 0;
285
+ };
286
+ return typeRank(a) - typeRank(b);
287
+ });
288
+ const content = tooltipRender(safeTitle, [
289
+ ...safeItems,
290
+ ...sortedCombineItems
291
+ ]) ?? null;
292
+ if (content && isTooltipContent) {
293
+ const domEvent = event?.event ?? event;
294
+ const canvas = container.querySelector('canvas');
295
+ const canvasRect = canvas ? canvas.getBoundingClientRect() : container.getBoundingClientRect();
296
+ const canvasX = domEvent?.canvasX ?? domEvent?.x ?? 0;
297
+ const canvasY = domEvent?.canvasY ?? domEvent?.y ?? 0;
298
+ const clientX = canvasRect.left + canvasX;
299
+ const clientY = canvasRect.top + canvasY;
300
+ const offsetX = 12;
301
+ const offsetY = 12;
302
+ const applyPosition = ()=>{
303
+ let el = content;
304
+ while(el && el.parentElement){
305
+ const p = el.parentElement;
306
+ if (p.classList?.contains('g2-tooltip')) {
355
307
  el = p;
308
+ break;
356
309
  }
357
- const wrapper = el && el.classList?.contains('g2-tooltip') ? el : null;
358
- if (!wrapper) return;
359
- const wRect = wrapper.getBoundingClientRect();
360
- const tooltipW = wRect.width || 260;
361
- const tooltipH = wRect.height || 300;
362
- const viewportWidth = window.innerWidth;
363
- const viewportHeight = window.innerHeight;
364
- let left = clientX + offsetX;
365
- let top = clientY + offsetY;
366
- if (left + tooltipW > viewportWidth - 10) left = clientX - tooltipW - offsetX;
367
- if (top + tooltipH > viewportHeight - 10) top = clientY - tooltipH - offsetY;
368
- if (left < 10) left = 10;
369
- if (top < 10) top = 10;
370
- wrapper.style.position = 'fixed';
371
- wrapper.style.left = `${left}px`;
372
- wrapper.style.top = `${top}px`;
373
- wrapper.style.transform = 'none';
374
- wrapper.style.pointerEvents = 'none';
375
- wrapper.style.zIndex = '99999';
376
- };
377
- try {
378
- applyPosition();
379
- requestAnimationFrame(applyPosition);
380
- } catch {}
381
- } else if (content && !isTooltipContent) {
382
- const domEvent = event?.event ?? event;
383
- const clientX = domEvent?.clientX ?? domEvent?.x ?? 0;
384
- const clientY = domEvent?.clientY ?? domEvent?.y ?? 0;
385
- const rect = container.getBoundingClientRect();
386
- const offsetX = 12;
387
- const offsetY = 12;
388
- const applyClamp = ()=>{
389
- let el = content;
390
- while(el && el.parentElement){
391
- const p = el.parentElement;
392
- if (p.classList?.contains('g2-tooltip')) {
393
- el = p;
394
- break;
395
- }
310
+ el = p;
311
+ }
312
+ const wrapper = el && el.classList?.contains('g2-tooltip') ? el : null;
313
+ if (!wrapper) return;
314
+ const wRect = wrapper.getBoundingClientRect();
315
+ const tooltipW = wRect.width || 260;
316
+ const tooltipH = wRect.height || 300;
317
+ const viewportWidth = window.innerWidth;
318
+ const viewportHeight = window.innerHeight;
319
+ let left = clientX + offsetX;
320
+ let top = clientY + offsetY;
321
+ if (left + tooltipW > viewportWidth - 10) left = clientX - tooltipW - offsetX;
322
+ if (top + tooltipH > viewportHeight - 10) top = clientY - tooltipH - offsetY;
323
+ if (left < 10) left = 10;
324
+ if (top < 10) top = 10;
325
+ wrapper.style.position = 'fixed';
326
+ wrapper.style.left = `${left}px`;
327
+ wrapper.style.top = `${top}px`;
328
+ wrapper.style.transform = 'none';
329
+ wrapper.style.pointerEvents = 'none';
330
+ wrapper.style.zIndex = '99999';
331
+ };
332
+ try {
333
+ applyPosition();
334
+ requestAnimationFrame(applyPosition);
335
+ } catch {}
336
+ } else if (content && !isTooltipContent) {
337
+ const domEvent = event?.event ?? event;
338
+ const clientX = domEvent?.clientX ?? domEvent?.x ?? 0;
339
+ const clientY = domEvent?.clientY ?? domEvent?.y ?? 0;
340
+ const rect = container.getBoundingClientRect();
341
+ const offsetX = 12;
342
+ const offsetY = 12;
343
+ const applyClamp = ()=>{
344
+ let el = content;
345
+ while(el && el.parentElement){
346
+ const p = el.parentElement;
347
+ if (p.classList?.contains('g2-tooltip')) {
396
348
  el = p;
349
+ break;
397
350
  }
398
- const wrapper = el && el.classList?.contains('g2-tooltip') ? el : null;
399
- if (!wrapper) return;
400
- const wRect = wrapper.getBoundingClientRect();
401
- const tooltipW = wRect.width || 260;
402
- const tooltipH = wRect.height || 300;
403
- const minLeft = rect.left;
404
- const maxLeft = rect.right - tooltipW;
405
- const minTop = rect.top;
406
- const maxTop = rect.bottom - tooltipH;
407
- const desiredLeft = clientX + offsetX;
408
- const desiredTop = clientY + offsetY;
409
- const left = Math.min(Math.max(desiredLeft, minLeft), Math.max(maxLeft, minLeft));
410
- const top = Math.min(Math.max(desiredTop, minTop), Math.max(maxTop, minTop));
411
- wrapper.style.position = 'fixed';
412
- wrapper.style.left = `${left}px`;
413
- wrapper.style.top = `${top}px`;
414
- wrapper.style.transform = 'translate(0px, 0px)';
415
- wrapper.style.pointerEvents = 'none';
416
- wrapper.style.zIndex = '9999';
417
- };
418
- try {
419
- applyClamp();
420
- requestAnimationFrame(applyClamp);
421
- } catch {}
422
- }
423
- return content;
351
+ el = p;
352
+ }
353
+ const wrapper = el && el.classList?.contains('g2-tooltip') ? el : null;
354
+ if (!wrapper) return;
355
+ const wRect = wrapper.getBoundingClientRect();
356
+ const tooltipW = wRect.width || 260;
357
+ const tooltipH = wRect.height || 300;
358
+ const minLeft = rect.left;
359
+ const maxLeft = rect.right - tooltipW;
360
+ const minTop = rect.top;
361
+ const maxTop = rect.bottom - tooltipH;
362
+ const desiredLeft = clientX + offsetX;
363
+ const desiredTop = clientY + offsetY;
364
+ const left = Math.min(Math.max(desiredLeft, minLeft), Math.max(maxLeft, minLeft));
365
+ const top = Math.min(Math.max(desiredTop, minTop), Math.max(maxTop, minTop));
366
+ wrapper.style.position = 'fixed';
367
+ wrapper.style.left = `${left}px`;
368
+ wrapper.style.top = `${top}px`;
369
+ wrapper.style.transform = 'translate(0px, 0px)';
370
+ wrapper.style.pointerEvents = 'none';
371
+ wrapper.style.zIndex = '9999';
372
+ };
373
+ try {
374
+ applyClamp();
375
+ requestAnimationFrame(applyClamp);
376
+ } catch {}
424
377
  }
425
- });
426
- }
378
+ return content;
379
+ }
380
+ });
427
381
  view.legend(false);
428
382
  view.interaction('poptip', {
429
383
  offsetY: -20,