@easyv/charts 1.10.24 → 1.10.26

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.
@@ -7,9 +7,8 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports["default"] = exports.calculateTextWidth = void 0;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
- var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
12
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
13
12
  var _react = _interopRequireWildcard(require("react"));
14
13
  var _utils = require("../utils");
15
14
  var _context = require("../context");
@@ -193,20 +192,71 @@ var Unit = function Unit(_ref4) {
193
192
  textAnchor: textAnchor
194
193
  }, dataUnit || text);
195
194
  };
195
+ function getLabelFormatterContext(config) {
196
+ var format = config.format,
197
+ showType = config.showType;
198
+ if (format && (0, _typeof2["default"])(format) === "object" && format.type != null) {
199
+ var _format$showType;
200
+ return _objectSpread(_objectSpread({}, config), {}, {
201
+ format: {
202
+ type: format.type,
203
+ showType: (_format$showType = format.showType) !== null && _format$showType !== void 0 ? _format$showType : showType
204
+ }
205
+ });
206
+ }
207
+ return _objectSpread(_objectSpread({}, config), {}, {
208
+ format: {
209
+ type: format,
210
+ showType: showType
211
+ }
212
+ });
213
+ }
214
+ function formatAxisLabel(label, config, formatter) {
215
+ return formatter(label, getLabelFormatterContext(config));
216
+ }
217
+ function buildUniformStepIndices(n, step) {
218
+ var indices = [];
219
+ for (var i = 0; i < n; i += step) {
220
+ indices.push(i);
221
+ }
222
+ return indices;
223
+ }
224
+ function satisfiesIndexSpacing(indices, xAt, minSpacing) {
225
+ for (var j = 1; j < indices.length; j++) {
226
+ if (xAt(indices[j]) - xAt(indices[j - 1]) < minSpacing) return false;
227
+ }
228
+ return true;
229
+ }
230
+ function getAdaptiveOrdinalTicks(allTicks, scaler, labelWidth, minGap) {
231
+ var n = allTicks.length;
232
+ if (!n) return [];
233
+ if (n === 1) return [allTicks[0]];
234
+ var minSpacing = labelWidth + minGap;
235
+ var xAt = function xAt(i) {
236
+ return scaler(allTicks[i]);
237
+ };
238
+
239
+ // 仅用相邻刻度像素间距约束,不用 floor(available/step) 限制数量:
240
+ // 极长标签时后者会得到 maxByWidth=1,错误地丢弃所有多刻度方案。
241
+ for (var step = 1; step < n; step++) {
242
+ var indices = buildUniformStepIndices(n, step);
243
+ if (satisfiesIndexSpacing(indices, xAt, minSpacing)) {
244
+ return indices.map(function (i) {
245
+ return allTicks[i];
246
+ });
247
+ }
248
+ }
249
+ if (n >= 2 && xAt(n - 1) - xAt(0) >= minSpacing) {
250
+ return [allTicks[0], allTicks[n - 1]];
251
+ }
252
+ return [allTicks[0]];
253
+ }
196
254
  function maxLabelFT(data, config, formatter, font, isVertical) {
197
255
  var max = 0;
198
256
  data.length ? data.forEach(function (item) {
199
- if (calculateTextWidth(formatter(item, _objectSpread(_objectSpread({}, config), {}, {
200
- format: {
201
- type: config.format,
202
- showType: config.showType
203
- }
204
- })), font, isVertical) > max) max = calculateTextWidth(formatter(item, _objectSpread(_objectSpread({}, config), {}, {
205
- format: {
206
- type: config.format,
207
- showType: config.showType
208
- }
209
- })), font, isVertical);
257
+ var formatted = formatAxisLabel(item, config, formatter);
258
+ var width = calculateTextWidth(formatted, font, isVertical);
259
+ if (width > max) max = width;
210
260
  }) : "";
211
261
  return max;
212
262
  }
@@ -245,12 +295,7 @@ var Label = function Label(_ref5) {
245
295
  textOverflow = _ref5$config$appearan2.textOverflow,
246
296
  LabelWidth = _ref5.LabelWidth;
247
297
  if (!show) return null;
248
- var _label = formatter(label, _objectSpread(_objectSpread({}, config), {}, {
249
- format: {
250
- type: config.format,
251
- showType: config.showType
252
- }
253
- }));
298
+ var _label = formatAxisLabel(label, config, formatter);
254
299
  var _getLayout = getLayout(orientation, adaptive ? 0 : rotate),
255
300
  transform = _getLayout.transform,
256
301
  directionX = _getLayout.directionX,
@@ -351,68 +396,12 @@ var _default = exports["default"] = /*#__PURE__*/(0, _react.memo)(/*#__PURE__*/(
351
396
  var LabelWidth = 1;
352
397
  if (!label.adaptive && label.appearance) {
353
398
  LabelWidth = label.appearance.width;
354
- } else {
355
- if (allTicks.length && typeof allTicks[0] == "string") {
356
- LabelWidth = maxLabelFT(allTicks, label, formatter, label.font, isVertical);
357
- }
399
+ } else if (allTicks.length) {
400
+ LabelWidth = Math.max(maxLabelFT(allTicks, label, formatter, label.font, isVertical), 1);
358
401
  }
359
- var LabelNum = !isVertical ? Math.floor(width / (isC ? cPercent : 1) * (1 - paddingOuter) / LabelWidth) : Math.floor(height / LabelWidth);
360
- var ticks = !label.adaptive ? tickss : getEvenlySpacedElements(allTicks, LabelNum < allTicks.length ? LabelNum > allTicks.length / 2 ? Math.ceil(allTicks.length / 2) : LabelNum : allTicks.length, label.showLast);
402
+ var LABEL_MIN_GAP = 12;
403
+ var ticks = !label.adaptive ? tickss : getAdaptiveOrdinalTicks(allTicks, scaler, LabelWidth, LABEL_MIN_GAP);
361
404
  if (!(on && ticks.length > 0)) return null;
362
-
363
- //数据抽取逻辑
364
- function getEvenlySpacedElements(arr, expectCount) {
365
- var acc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
366
- if (!arr.length || expectCount <= 0) return [];
367
- if (expectCount >= arr.length) return (0, _toConsumableArray2["default"])(arr);
368
- if (expectCount === 1) return [arr[0]];
369
- if (acc) {
370
- var totalLength = arr.length;
371
- var result = [];
372
- var bestCount = 2;
373
- for (var k = expectCount; k >= 2; k--) {
374
- var denominator = k - 1;
375
- var numerator = totalLength - 1;
376
- if (denominator > 0 && numerator % denominator === 0) {
377
- bestCount = k;
378
- break;
379
- }
380
- }
381
- var step = (totalLength - 1) / (bestCount - 1);
382
- for (var i = 0; i < bestCount; i++) {
383
- var rawIndex = i * step;
384
- var index = Math.ceil(rawIndex);
385
- var safeIndex = Math.max(0, Math.min(totalLength - 1, index));
386
- result.push(arr[safeIndex]);
387
- }
388
- if (result.length > 0) result[0] = arr[0];
389
- if (result.length >= 2) result[result.length - 1] = arr[totalLength - 1];
390
- return result;
391
- } else {
392
- // 重构acc=false逻辑:优先均匀分布,不强制首尾
393
- var _result = [];
394
- var arrLen = arr.length;
395
- if (expectCount === 2) {
396
- _result.push(arr[0]);
397
- _result.push(arr[arrLen - 1]);
398
- return _result;
399
- }
400
- var idealStep = (arrLen - 1) / (expectCount - 1);
401
- var isIdealStepInteger = Math.abs(idealStep - Math.round(idealStep)) < 1e-10;
402
- if (isIdealStepInteger) {
403
- for (var _i = 0; _i < expectCount; _i++) {
404
- var _index = _i * idealStep;
405
- _result.push(arr[_index]);
406
- }
407
- } else {
408
- var _step = Math.max(1, Math.floor(arrLen / expectCount));
409
- for (var _i2 = 0; _i2 < arrLen && _result.length < expectCount; _i2 += _step) {
410
- _result.push(arr[_i2]);
411
- }
412
- }
413
- return _result;
414
- }
415
- }
416
405
  function drawAxisTickLine() {
417
406
  var draw = function draw(ticks, scaler) {
418
407
  return ticks.map(function (tick, index) {
@@ -259,9 +259,10 @@ var _default = exports["default"] = /*#__PURE__*/(0, _react.memo)(function (_ref
259
259
  triggerEvents ? triggerEvents(e, "setCurrent") : "";
260
260
  },
261
261
  onMouseMove: function onMouseMove(e) {
262
- triggerEvents ? handleMouseMove : "";
262
+ triggerEvents ? handleMouseMove(e) : "";
263
263
  },
264
- onMouseEnter: function onMouseEnter() {
264
+ onMouseEnter: function onMouseEnter(e) {
265
+ triggerEvents ? triggerEvents(e, "mouseenter") : "";
265
266
  if (isControlChart) {
266
267
  setCtlTip(function (pre) {
267
268
  return {
@@ -162,7 +162,15 @@ var _default = exports["default"] = /*#__PURE__*/(0, _react.memo)(function (_ref
162
162
  });
163
163
  return /*#__PURE__*/_react["default"].createElement("g", {
164
164
  key: i,
165
- onClick: triggerEvents,
165
+ onClick: function onClick(e) {
166
+ triggerEvents ? triggerEvents(e, "setCurrent") : "";
167
+ },
168
+ onMouseEnter: function onMouseEnter(e) {
169
+ triggerEvents ? triggerEvents(e, "mouseenter") : "";
170
+ },
171
+ onMouseLeave: function onMouseLeave(e) {
172
+ triggerEvents ? triggerEvents(e, "mouseleave") : "";
173
+ },
166
174
  "data-data": JSON.stringify(data)
167
175
  }, /*#__PURE__*/_react["default"].createElement(Column3DSkin, (0, _extends2["default"])({}, attr, {
168
176
  color: extent === flag ? highlightColor : color
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easyv/charts",
3
- "version": "1.10.24",
3
+ "version": "1.10.26",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -248,6 +248,74 @@ type LabelType = {
248
248
  LabelWidth: any;
249
249
  };
250
250
 
251
+ function getLabelFormatterContext(config: any) {
252
+ const { format, showType } = config;
253
+ if (format && typeof format === "object" && format.type != null) {
254
+ return {
255
+ ...config,
256
+ format: {
257
+ type: format.type,
258
+ showType: format.showType ?? showType,
259
+ },
260
+ };
261
+ }
262
+ return {
263
+ ...config,
264
+ format: { type: format, showType },
265
+ };
266
+ }
267
+
268
+ function formatAxisLabel(label: any, config: any, formatter: any) {
269
+ return formatter(label, getLabelFormatterContext(config));
270
+ }
271
+
272
+ function buildUniformStepIndices(n: number, step: number): number[] {
273
+ const indices: number[] = [];
274
+ for (let i = 0; i < n; i += step) {
275
+ indices.push(i);
276
+ }
277
+ return indices;
278
+ }
279
+
280
+ function satisfiesIndexSpacing(
281
+ indices: number[],
282
+ xAt: (i: number) => number,
283
+ minSpacing: number,
284
+ ) {
285
+ for (let j = 1; j < indices.length; j++) {
286
+ if (xAt(indices[j]) - xAt(indices[j - 1]) < minSpacing) return false;
287
+ }
288
+ return true;
289
+ }
290
+
291
+ function getAdaptiveOrdinalTicks(
292
+ allTicks: any[],
293
+ scaler: any,
294
+ labelWidth: number,
295
+ minGap: number,
296
+ ) {
297
+ const n = allTicks.length;
298
+ if (!n) return [];
299
+ if (n === 1) return [allTicks[0]];
300
+
301
+ const minSpacing = labelWidth + minGap;
302
+ const xAt = (i: number) => scaler(allTicks[i]);
303
+
304
+ // 仅用相邻刻度像素间距约束,不用 floor(available/step) 限制数量:
305
+ // 极长标签时后者会得到 maxByWidth=1,错误地丢弃所有多刻度方案。
306
+ for (let step = 1; step < n; step++) {
307
+ const indices = buildUniformStepIndices(n, step);
308
+ if (satisfiesIndexSpacing(indices, xAt, minSpacing)) {
309
+ return indices.map((i) => allTicks[i]);
310
+ }
311
+ }
312
+
313
+ if (n >= 2 && xAt(n - 1) - xAt(0) >= minSpacing) {
314
+ return [allTicks[0], allTicks[n - 1]];
315
+ }
316
+ return [allTicks[0]];
317
+ }
318
+
251
319
  function maxLabelFT(
252
320
  data: any,
253
321
  config: any,
@@ -258,24 +326,9 @@ function maxLabelFT(
258
326
  let max = 0;
259
327
  data.length
260
328
  ? data.forEach((item: any) => {
261
- if (
262
- calculateTextWidth(
263
- formatter(item, {
264
- ...config,
265
- format: { type: config.format, showType: config.showType },
266
- }),
267
- font,
268
- isVertical,
269
- ) > max
270
- )
271
- max = calculateTextWidth(
272
- formatter(item, {
273
- ...config,
274
- format: { type: config.format, showType: config.showType },
275
- }),
276
- font,
277
- isVertical,
278
- );
329
+ const formatted = formatAxisLabel(item, config, formatter);
330
+ const width = calculateTextWidth(formatted, font, isVertical);
331
+ if (width > max) max = width;
279
332
  })
280
333
  : "";
281
334
  return max;
@@ -305,10 +358,7 @@ const Label: (
305
358
  LabelWidth,
306
359
  }) => {
307
360
  if (!show) return null;
308
- const _label = formatter(label, {
309
- ...config,
310
- format: { type: config.format, showType: config.showType },
311
- });
361
+ const _label = formatAxisLabel(label, config, formatter);
312
362
  const { transform, directionX, directionY } = getLayout(
313
363
  orientation,
314
364
  adaptive ? 0 : rotate,
@@ -420,104 +470,29 @@ export default memo(
420
470
  let LabelWidth = 1;
421
471
  if (!label.adaptive && label.appearance) {
422
472
  LabelWidth = label.appearance.width;
423
- } else {
424
- if (allTicks.length && typeof allTicks[0] == "string") {
425
- LabelWidth = maxLabelFT(
473
+ } else if (allTicks.length) {
474
+ LabelWidth = Math.max(
475
+ maxLabelFT(
426
476
  allTicks,
427
477
  label,
428
478
  formatter,
429
479
  label.font,
430
480
  isVertical,
431
- );
432
- }
481
+ ),
482
+ 1,
483
+ );
433
484
  }
434
- const LabelNum = !isVertical
435
- ? Math.floor(
436
- ((width / (isC ? cPercent : 1)) * (1 - paddingOuter)) / LabelWidth,
437
- )
438
- : Math.floor(height / LabelWidth);
439
-
485
+ const LABEL_MIN_GAP = 12;
440
486
  const ticks: any = !label.adaptive
441
487
  ? tickss
442
- : getEvenlySpacedElements(
488
+ : getAdaptiveOrdinalTicks(
443
489
  allTicks,
444
- LabelNum < allTicks.length
445
- ? LabelNum > allTicks.length / 2
446
- ? Math.ceil(allTicks.length / 2)
447
- : LabelNum
448
- : allTicks.length,
449
- label.showLast,
490
+ scaler,
491
+ LabelWidth,
492
+ LABEL_MIN_GAP,
450
493
  );
451
494
  if (!(on && ticks.length > 0)) return null;
452
495
 
453
- //数据抽取逻辑
454
- function getEvenlySpacedElements(
455
- arr: any[],
456
- expectCount: number,
457
- acc: boolean = false,
458
- ): any[] {
459
- if (!arr.length || expectCount <= 0) return [];
460
- if (expectCount >= arr.length) return [...arr];
461
- if (expectCount === 1) return [arr[0]];
462
-
463
- if (acc) {
464
- const totalLength = arr.length;
465
- const result: any[] = [];
466
-
467
- let bestCount = 2;
468
- for (let k = expectCount; k >= 2; k--) {
469
- const denominator = k - 1;
470
- const numerator = totalLength - 1;
471
- if (denominator > 0 && numerator % denominator === 0) {
472
- bestCount = k;
473
- break;
474
- }
475
- }
476
-
477
- const step = (totalLength - 1) / (bestCount - 1);
478
- for (let i = 0; i < bestCount; i++) {
479
- const rawIndex = i * step;
480
- const index = Math.ceil(rawIndex);
481
- const safeIndex = Math.max(0, Math.min(totalLength - 1, index));
482
- result.push(arr[safeIndex]);
483
- }
484
-
485
- if (result.length > 0) result[0] = arr[0];
486
- if (result.length >= 2)
487
- result[result.length - 1] = arr[totalLength - 1];
488
-
489
- return result;
490
- } else {
491
- // 重构acc=false逻辑:优先均匀分布,不强制首尾
492
- const result: any[] = [];
493
- const arrLen = arr.length;
494
- if (expectCount === 2) {
495
- result.push(arr[0]);
496
- result.push(arr[arrLen - 1]);
497
- return result;
498
- }
499
- const idealStep = (arrLen - 1) / (expectCount - 1);
500
- const isIdealStepInteger =
501
- Math.abs(idealStep - Math.round(idealStep)) < 1e-10;
502
-
503
- if (isIdealStepInteger) {
504
- for (let i = 0; i < expectCount; i++) {
505
- const index = i * idealStep;
506
- result.push(arr[index]);
507
- }
508
- } else {
509
- const step = Math.max(1, Math.floor(arrLen / expectCount));
510
- for (
511
- let i = 0;
512
- i < arrLen && result.length < expectCount;
513
- i += step
514
- ) {
515
- result.push(arr[i]);
516
- }
517
- }
518
- return result;
519
- }
520
- }
521
496
  function drawAxisTickLine() {
522
497
  const draw = (ticks: any, scaler: any) => {
523
498
  return ticks.map((tick: string, index: number) => {
@@ -93,8 +93,8 @@ const getBorderRadius = ({
93
93
  ? "0px " + seriesWidth + "px " + seriesWidth + "px 0"
94
94
  : seriesWidth + "px 0 0 " + seriesWidth + "px"
95
95
  : positive
96
- ? seriesWidth / 2 + "px " + seriesWidth / 2 + "px 0 0"
97
- : "0 0 " + seriesWidth / 2 + "px " + seriesWidth / 2 + "px";
96
+ ? seriesWidth / 2 + "px " + seriesWidth / 2 + "px 0 0"
97
+ : "0 0 " + seriesWidth / 2 + "px " + seriesWidth / 2 + "px";
98
98
  };
99
99
 
100
100
  export default memo(
@@ -157,7 +157,7 @@ export default memo(
157
157
  triggerEvents(e, "setCurrent");
158
158
  }
159
159
  }, 100), // 每 100ms 最多执行一次
160
- [triggerEvents]
160
+ [triggerEvents],
161
161
  );
162
162
  return (
163
163
  <g className="__easyv-band">
@@ -170,7 +170,7 @@ export default memo(
170
170
  data,
171
171
  data: { x, y, s },
172
172
  }: DataWithBoundType,
173
- i: number
173
+ i: number,
174
174
  ) => {
175
175
  let y1: number, y2: number;
176
176
  //断轴图相关,断轴图的scaler是一个数组,内含上断轴下断轴的scaler
@@ -214,13 +214,13 @@ export default memo(
214
214
  headHeight,
215
215
  headTranslate;
216
216
  if (headDecorate) {
217
- (showHead = headDecorate.show),
217
+ ((showHead = headDecorate.show),
218
218
  (headType = headDecorate.type),
219
219
  (headUrl = headDecorate.url),
220
220
  (headVideo = headDecorate.video),
221
221
  (headWidth = headDecorate.size.width),
222
222
  (headHeight = headDecorate.size.height),
223
- (headTranslate = headDecorate.translate);
223
+ (headTranslate = headDecorate.translate));
224
224
  }
225
225
  //断轴图相关,将柱形在断轴处切开
226
226
  const setClipPath = () => {
@@ -259,9 +259,10 @@ export default memo(
259
259
  triggerEvents ? triggerEvents(e, "setCurrent") : "";
260
260
  }}
261
261
  onMouseMove={(e) => {
262
- triggerEvents ? handleMouseMove : "";
262
+ triggerEvents ? handleMouseMove(e) : "";
263
263
  }}
264
- onMouseEnter={() => {
264
+ onMouseEnter={(e) => {
265
+ triggerEvents ? triggerEvents(e, "mouseenter") : "";
265
266
  if (isControlChart) {
266
267
  setCtlTip((pre: any) => ({
267
268
  show: true,
@@ -363,7 +364,7 @@ export default memo(
363
364
  : getBandBackground(
364
365
  pattern,
365
366
  fill,
366
- y //是否小于0
367
+ y, //是否小于0
367
368
  ),
368
369
  borderRadius:
369
370
  style == "square"
@@ -398,9 +399,9 @@ export default memo(
398
399
  </foreignObject>
399
400
  </Fragment>
400
401
  );
401
- }
402
+ },
402
403
  )}
403
404
  </g>
404
405
  );
405
- }
406
+ },
406
407
  );
@@ -174,7 +174,15 @@ export default memo(
174
174
  return (
175
175
  <g
176
176
  key={i}
177
- onClick={triggerEvents}
177
+ onClick={(e) => {
178
+ triggerEvents ? triggerEvents(e, "setCurrent") : "";
179
+ }}
180
+ onMouseEnter={(e) => {
181
+ triggerEvents ? triggerEvents(e, "mouseenter") : "";
182
+ }}
183
+ onMouseLeave={(e) => {
184
+ triggerEvents ? triggerEvents(e, "mouseleave") : "";
185
+ }}
178
186
  data-data={JSON.stringify(data)}
179
187
  >
180
188
  <Column3DSkin