zrender-nightly 5.7.0-dev.20250620 → 5.7.0-dev.20250621

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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/build/prepublish.js +20 -0
  3. package/dist/zrender.js +563 -277
  4. package/dist/zrender.js.map +1 -1
  5. package/dist/zrender.min.js +1 -1
  6. package/lib/Element.d.ts +4 -0
  7. package/lib/Element.js +34 -16
  8. package/lib/Handler.js +1 -1
  9. package/lib/Storage.js +20 -20
  10. package/lib/canvas/graphic.js +1 -1
  11. package/lib/contain/text.d.ts +14 -2
  12. package/lib/contain/text.js +65 -15
  13. package/lib/core/BoundingRect.d.ts +25 -3
  14. package/lib/core/BoundingRect.js +182 -76
  15. package/lib/core/OrientedBoundingRect.d.ts +2 -2
  16. package/lib/core/OrientedBoundingRect.js +50 -34
  17. package/lib/core/PathProxy.d.ts +1 -0
  18. package/lib/core/PathProxy.js +16 -1
  19. package/lib/core/dom.d.ts +1 -0
  20. package/lib/core/dom.js +17 -0
  21. package/lib/core/env.js +15 -10
  22. package/lib/core/types.d.ts +1 -0
  23. package/lib/core/util.d.ts +1 -0
  24. package/lib/core/util.js +2 -1
  25. package/lib/graphic/Displayable.js +1 -1
  26. package/lib/graphic/Text.d.ts +4 -2
  27. package/lib/graphic/Text.js +23 -14
  28. package/lib/graphic/helper/parseText.d.ts +13 -4
  29. package/lib/graphic/helper/parseText.js +110 -54
  30. package/lib/svg-legacy/helper/ClippathManager.js +6 -6
  31. package/lib/tool/color.d.ts +3 -1
  32. package/lib/tool/color.js +6 -6
  33. package/lib/tool/parseSVG.js +11 -0
  34. package/lib/tool/path.js +7 -4
  35. package/lib/zrender.d.ts +1 -1
  36. package/lib/zrender.js +1 -1
  37. package/package.json +3 -2
  38. package/src/Element.ts +69 -16
  39. package/src/Handler.ts +1 -1
  40. package/src/Storage.ts +25 -24
  41. package/src/canvas/graphic.ts +1 -1
  42. package/src/canvas/helper.ts +1 -1
  43. package/src/contain/text.ts +103 -19
  44. package/src/core/BoundingRect.ts +308 -87
  45. package/src/core/OrientedBoundingRect.ts +86 -46
  46. package/src/core/PathProxy.ts +17 -1
  47. package/src/core/Transformable.ts +2 -0
  48. package/src/core/dom.ts +24 -0
  49. package/src/core/env.ts +31 -24
  50. package/src/core/matrix.ts +2 -1
  51. package/src/core/types.ts +2 -0
  52. package/src/core/util.ts +4 -2
  53. package/src/graphic/Displayable.ts +1 -3
  54. package/src/graphic/Group.ts +2 -0
  55. package/src/graphic/Text.ts +68 -21
  56. package/src/graphic/helper/parseText.ts +211 -83
  57. package/src/svg-legacy/helper/ClippathManager.ts +5 -5
  58. package/src/tool/color.ts +15 -11
  59. package/src/tool/parseSVG.ts +12 -1
  60. package/src/tool/path.ts +9 -4
  61. package/src/zrender.ts +1 -1
@@ -365,6 +365,9 @@ export default class PathProxy {
365
365
  }
366
366
 
367
367
  setData(data: Float32Array | number[]) {
368
+ if (!this._saveData) {
369
+ return;
370
+ }
368
371
 
369
372
  const len = data.length;
370
373
 
@@ -380,6 +383,9 @@ export default class PathProxy {
380
383
  }
381
384
 
382
385
  appendPath(path: PathProxy | PathProxy[]) {
386
+ if (!this._saveData) {
387
+ return;
388
+ }
383
389
  if (!(path instanceof Array)) {
384
390
  path = [path];
385
391
  }
@@ -389,8 +395,14 @@ export default class PathProxy {
389
395
  for (let i = 0; i < len; i++) {
390
396
  appendSize += path[i].len();
391
397
  }
392
- if (hasTypedArray && (this.data instanceof Float32Array)) {
398
+ const oldData = this.data;
399
+ if (hasTypedArray && (oldData instanceof Float32Array || !oldData)) {
393
400
  this.data = new Float32Array(offset + appendSize);
401
+ if (offset > 0 && oldData) {
402
+ for (let k = 0; k < offset; k++) {
403
+ this.data[k] = oldData[k];
404
+ }
405
+ }
394
406
  }
395
407
  for (let i = 0; i < len; i++) {
396
408
  const appendPathData = path[i].data;
@@ -970,6 +982,10 @@ export default class PathProxy {
970
982
  return newProxy;
971
983
  }
972
984
 
985
+ canSave(): boolean {
986
+ return !!this._saveData;
987
+ }
988
+
973
989
  private static initDefaultProps = (function () {
974
990
  const proto = PathProxy.prototype;
975
991
  proto._saveData = true;
@@ -27,6 +27,8 @@ class Transformable {
27
27
  skewX: number
28
28
  skewY: number
29
29
 
30
+ // Suppose positive y is towards screen-bottom and positive x is towards screen-right;
31
+ // positive rotation means rotating anticlockwise. (opposite to CSS transform rotate)
30
32
  rotation: number
31
33
 
32
34
  /**
package/src/core/dom.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  import env from './env';
3
3
  import {buildTransformer} from './fourPointsTransform';
4
4
  import {Dictionary} from './types';
5
+ import { each } from './util';
5
6
 
6
7
  const EVENT_SAVED_PROP = '___zrEVENTSAVED';
7
8
  const _calcOut: number[] = [];
@@ -11,6 +12,7 @@ type SavedInfo = {
11
12
  trans?: ReturnType<typeof buildTransformer>
12
13
  invTrans?: ReturnType<typeof buildTransformer>
13
14
  srcCoords?: number[]
15
+ clearMarkers?: () => void
14
16
  }
15
17
 
16
18
  /**
@@ -57,6 +59,22 @@ export function transformLocalCoord(
57
59
  && transformCoordWithViewport(out, elTarget, _calcOut[0], _calcOut[1]);
58
60
  }
59
61
 
62
+ export function transformLocalCoordClear(
63
+ elFrom: HTMLElement,
64
+ elTarget: HTMLElement,
65
+ ) {
66
+ elFrom && dealClear(elFrom);
67
+ elTarget && dealClear(elTarget);
68
+
69
+ function dealClear(el: HTMLElement) {
70
+ const saved: SavedInfo = (el as any)[EVENT_SAVED_PROP];
71
+ if (saved) {
72
+ saved.clearMarkers && saved.clearMarkers();
73
+ delete (el as any)[EVENT_SAVED_PROP];
74
+ }
75
+ }
76
+ }
77
+
60
78
  /**
61
79
  * Transform between a "viewport coord" and a "local coord".
62
80
  * "viewport coord": the coord based on the left-top corner of the viewport
@@ -134,6 +152,12 @@ function prepareCoordMarkers(el: HTMLElement, saved: SavedInfo) {
134
152
  markers.push(marker);
135
153
  }
136
154
 
155
+ saved.clearMarkers = function () {
156
+ each(markers, function (marker) {
157
+ marker.parentNode && marker.parentNode.removeChild(marker);
158
+ });
159
+ };
160
+
137
161
  return markers;
138
162
  }
139
163
 
package/src/core/env.ts CHANGED
@@ -37,7 +37,12 @@ else if (typeof document === 'undefined' && typeof self !== 'undefined') {
37
37
  // In worker
38
38
  env.worker = true;
39
39
  }
40
- else if (!env.hasGlobalWindow || 'Deno' in window) {
40
+ else if (
41
+ !env.hasGlobalWindow
42
+ || 'Deno' in window
43
+ || (typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string'
44
+ && navigator.userAgent.indexOf('Node.js') > -1)
45
+ ) {
41
46
  // In node
42
47
  env.node = true;
43
48
  env.svgSupported = true;
@@ -85,29 +90,31 @@ function detect(ua: string, env: Env) {
85
90
  env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge;
86
91
  env.pointerEventsSupported = 'onpointerdown' in window
87
92
  && (browser.edge || (browser.ie && +browser.version >= 11));
88
- env.domSupported = typeof document !== 'undefined';
89
-
90
- const style = document.documentElement.style;
91
-
92
- env.transform3dSupported = (
93
- // IE9 only supports transform 2D
94
- // transform 3D supported since IE10
95
- // we detect it by whether 'transition' is in style
96
- (browser.ie && 'transition' in style)
97
- // edge
98
- || browser.edge
99
- // webkit
100
- || (('WebKitCSSMatrix' in window) && ('m11' in new WebKitCSSMatrix()))
101
- // gecko-based browsers
102
- || 'MozPerspective' in style
103
- ) // Opera supports CSS transforms after version 12
104
- && !('OTransition' in style);
105
-
106
- // except IE 6-8 and very old firefox 2-3 & opera 10.1
107
- // other browsers all support `transform`
108
- env.transformSupported = env.transform3dSupported
109
- // transform 2D is supported in IE9
110
- || (browser.ie && +browser.version >= 9);
93
+
94
+ const domSupported = env.domSupported = typeof document !== 'undefined';
95
+ if (domSupported) {
96
+ const style = document.documentElement.style;
97
+
98
+ env.transform3dSupported = (
99
+ // IE9 only supports transform 2D
100
+ // transform 3D supported since IE10
101
+ // we detect it by whether 'transition' is in style
102
+ (browser.ie && 'transition' in style)
103
+ // edge
104
+ || browser.edge
105
+ // webkit
106
+ || (('WebKitCSSMatrix' in window) && ('m11' in new WebKitCSSMatrix()))
107
+ // gecko-based browsers
108
+ || 'MozPerspective' in style
109
+ ) // Opera supports CSS transforms after version 12
110
+ && !('OTransition' in style);
111
+
112
+ // except IE 6-8 and very old firefox 2-3 & opera 10.1
113
+ // other browsers all support `transform`
114
+ env.transformSupported = env.transform3dSupported
115
+ // transform 2D is supported in IE9
116
+ || (browser.ie && +browser.version >= 9);
117
+ }
111
118
 
112
119
  }
113
120
 
@@ -77,7 +77,8 @@ export function translate(out: MatrixArray, a: MatrixArray, v: VectorArray): Mat
77
77
  }
78
78
 
79
79
  /**
80
- * 旋转变换
80
+ * Suppose positive y is towards screen-bottom and positive x is towards screen-right;
81
+ * positive rotation means rotating anticlockwise. (opposite to CSS transform rotate)
81
82
  */
82
83
  export function rotate(
83
84
  out: MatrixArray,
package/src/core/types.ts CHANGED
@@ -11,6 +11,8 @@ export type ArrayLike<T> = {
11
11
  length: number
12
12
  }
13
13
 
14
+ export type NullUndefined = null | undefined;
15
+
14
16
  export type ImageLike = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement
15
17
 
16
18
  // subset of CanvasTextBaseline
package/src/core/util.ts CHANGED
@@ -203,7 +203,7 @@ export function defaults<
203
203
  S extends Dictionary<any>
204
204
  >(target: T, source: S, overlay?: boolean): T & S {
205
205
  const keysArr = keys(source);
206
- for (let i = 0; i < keysArr.length; i++) {
206
+ for (let i = 0, len = keysArr.length; i < len; i++) {
207
207
  let key = keysArr[i];
208
208
  if ((overlay ? source[key] != null : (target as T & S)[key] == null)) {
209
209
  (target as S & T)[key] = (source as T & S)[key];
@@ -819,4 +819,6 @@ export function hasOwn(own: object, prop: string): boolean {
819
819
 
820
820
  export function noop() {}
821
821
 
822
- export const RADIAN_TO_DEGREE = 180 / Math.PI;
822
+ export const RADIAN_TO_DEGREE = 180 / Math.PI;
823
+
824
+ export const EPSILON = Number.EPSILON || Math.pow(2, -52);
@@ -154,8 +154,6 @@ class Displayable<Props extends DisplayableProps = DisplayableProps> extends Ele
154
154
  // TODO use WeakMap?
155
155
 
156
156
  // Shapes for cascade clipping.
157
- // Can only be `null`/`undefined` or an non-empty array, MUST NOT be an empty array.
158
- // because it is easy to only using null to check whether clipPaths changed.
159
157
  __clipPaths?: Path[]
160
158
 
161
159
  // FOR CANVAS PAINTER
@@ -223,7 +221,7 @@ class Displayable<Props extends DisplayableProps = DisplayableProps> extends Ele
223
221
  return false;
224
222
  }
225
223
 
226
- if (considerClipPath && this.__clipPaths) {
224
+ if (considerClipPath && this.__clipPaths && this.__clipPaths.length) {
227
225
  for (let i = 0; i < this.__clipPaths.length; ++i) {
228
226
  if (this.__clipPaths[i].isZeroArea()) {
229
227
  return false;
@@ -256,6 +256,8 @@ class Group extends Element<GroupProps> {
256
256
 
257
257
  getBoundingRect(includeChildren?: Element[]): BoundingRect {
258
258
  // TODO Caching
259
+ // FIXME: if no child or all ignored, the returned boundingRect (0, 0, 0, 0)
260
+ // is not a correct bounding rect in some scenarios, such as rect union and intersection detection.
259
261
  const tmpRect = new BoundingRect(0, 0, 0, 0);
260
262
  const children = includeChildren || this._children;
261
263
  const tmpMat: MatrixArray = [];
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * RichText is a container that manages complex text label.
3
- * It will parse text string and create sub displayble elements respectively.
3
+ * It will parse text string and create sub displayable elements respectively.
4
4
  */
5
- import { TextAlign, TextVerticalAlign, ImageLike, Dictionary, MapToType, FontWeight, FontStyle } from '../core/types';
6
- import { parseRichText, parsePlainText } from './helper/parseText';
5
+ import {
6
+ TextAlign, TextVerticalAlign, ImageLike, Dictionary, MapToType, FontWeight, FontStyle, NullUndefined
7
+ } from '../core/types';
8
+ import {
9
+ parseRichText, parsePlainText, CalcInnerTextOverflowAreaOut, calcInnerTextOverflowArea
10
+ } from './helper/parseText';
7
11
  import TSpan, { TSpanStyleProps } from './TSpan';
8
12
  import { retrieve2, each, normalizeCssArray, trim, retrieve3, extend, keys, defaults } from '../core/util';
9
13
  import { adjustTextX, adjustTextY } from '../contain/text';
@@ -41,7 +45,7 @@ export interface TextStylePropsPart {
41
45
  strokeOpacity?: number
42
46
  /**
43
47
  * textStroke may be set as some color as a default
44
- * value in upper applicaion, where the default value
48
+ * value in upper application, where the default value
45
49
  * of lineWidth should be 0 to make sure that
46
50
  * user can choose to do not use text stroke.
47
51
  */
@@ -92,6 +96,7 @@ export interface TextStylePropsPart {
92
96
  /**
93
97
  * Width of text block. Not include padding
94
98
  * Used for background, truncate, wrap
99
+ * If string - be 'auto'.
95
100
  */
96
101
  width?: number | string
97
102
  /**
@@ -100,7 +105,7 @@ export interface TextStylePropsPart {
100
105
  */
101
106
  height?: number
102
107
  /**
103
- * Reserved for special functinality, like 'hr'.
108
+ * Reserved for special functionality, like 'hr'.
104
109
  */
105
110
  tag?: string
106
111
 
@@ -121,7 +126,7 @@ export interface TextStylePropsPart {
121
126
  /**
122
127
  * Margin of label. Used when layouting the label.
123
128
  */
124
- margin?: number
129
+ margin?: number | number[]
125
130
 
126
131
  borderColor?: string
127
132
  borderWidth?: number
@@ -148,6 +153,10 @@ export interface TextStyleProps extends TextStylePropsPart {
148
153
 
149
154
  text?: string
150
155
 
156
+ /**
157
+ * The outer rect (including padding) is placed based on x/y.
158
+ * By default 0.
159
+ */
151
160
  x?: number
152
161
  y?: number
153
162
 
@@ -155,6 +164,7 @@ export interface TextStyleProps extends TextStylePropsPart {
155
164
  * Only support number in the top block.
156
165
  */
157
166
  width?: number
167
+
158
168
  /**
159
169
  * Text styles for rich text.
160
170
  */
@@ -204,6 +214,9 @@ export type TextState = Pick<TextProps, DisplayableStatePropNames> & ElementComm
204
214
 
205
215
  export type DefaultTextStyle = Pick<TextStyleProps, 'fill' | 'stroke' | 'align' | 'verticalAlign'> & {
206
216
  autoStroke?: boolean
217
+ // In text local coord.
218
+ // Exist if and only if `ElementTextConfig['autoOverflowArea']: true`
219
+ overflowRect?: BoundingRect | NullUndefined
207
220
  };
208
221
 
209
222
  const DEFAULT_RICH_TEXT_COLOR = {
@@ -211,6 +224,8 @@ const DEFAULT_RICH_TEXT_COLOR = {
211
224
  };
212
225
  const DEFAULT_STROKE_LINE_WIDTH = 2;
213
226
 
227
+ const tmpCITOverflowAreaOut = {} as CalcInnerTextOverflowAreaOut;
228
+
214
229
  // const DEFAULT_TEXT_STYLE: TextStyleProps = {
215
230
  // x: 0,
216
231
  // y: 0,
@@ -270,11 +285,17 @@ class ZRText extends Displayable<TextProps> implements GroupLike {
270
285
 
271
286
  /**
272
287
  * Will use this to calculate transform matrix
273
- * instead of Element itseelf if it's give.
288
+ * instead of Element itself if it's give.
274
289
  * Not exposed to developers
275
290
  */
276
291
  innerTransformable: Transformable
277
292
 
293
+ // Be `true` if and only if the result text is modified due to overflow, due to
294
+ // settings on either `overflow` or `lineOverflow`. Based on this the caller can
295
+ // take some action like showing the original text in a particular tip.
296
+ // Only take effect after rendering. So do not visit it before it.
297
+ isTruncated: boolean
298
+
278
299
  private _children: (ZRImage | Rect | TSpan)[] = []
279
300
 
280
301
  private _childCursor: 0
@@ -483,8 +504,25 @@ class ZRText extends Displayable<TextProps> implements GroupLike {
483
504
  const textFont = style.font || DEFAULT_FONT;
484
505
  const textPadding = style.padding as number[];
485
506
 
507
+ const defaultStyle = this._defaultStyle;
508
+ let baseX = style.x || 0;
509
+ let baseY = style.y || 0;
510
+ const textAlign = style.align || defaultStyle.align || 'left';
511
+ const verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top';
512
+
513
+ calcInnerTextOverflowArea(
514
+ tmpCITOverflowAreaOut, defaultStyle.overflowRect, baseX, baseY, textAlign, verticalAlign
515
+ );
516
+ baseX = tmpCITOverflowAreaOut.baseX;
517
+ baseY = tmpCITOverflowAreaOut.baseY;
518
+
486
519
  const text = getStyleText(style);
487
- const contentBlock = parsePlainText(text, style);
520
+ const contentBlock = parsePlainText(
521
+ text,
522
+ style,
523
+ tmpCITOverflowAreaOut.outerWidth,
524
+ tmpCITOverflowAreaOut.outerHeight
525
+ );
488
526
  const needDrawBg = needDrawBackground(style);
489
527
  const bgColorDrawn = !!(style.backgroundColor);
490
528
 
@@ -495,12 +533,7 @@ class ZRText extends Displayable<TextProps> implements GroupLike {
495
533
  const textLines = contentBlock.lines;
496
534
  const lineHeight = contentBlock.lineHeight;
497
535
 
498
- const defaultStyle = this._defaultStyle;
499
-
500
- const baseX = style.x || 0;
501
- const baseY = style.y || 0;
502
- const textAlign = style.align || defaultStyle.align || 'left';
503
- const verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top';
536
+ this.isTruncated = !!contentBlock.isTruncated;
504
537
 
505
538
  let textX = baseX;
506
539
  let textY = adjustTextY(baseY, contentBlock.contentHeight, verticalAlign);
@@ -602,7 +635,7 @@ class ZRText extends Displayable<TextProps> implements GroupLike {
602
635
 
603
636
  if (fixedBoundingRect) {
604
637
  el.setBoundingRect(new BoundingRect(
605
- adjustTextX(subElStyle.x, style.width, subElStyle.textAlign as TextAlign),
638
+ adjustTextX(subElStyle.x, contentWidth, subElStyle.textAlign as TextAlign),
606
639
  adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline as TextVerticalAlign),
607
640
  /**
608
641
  * Text boundary should be the real text width.
@@ -619,21 +652,35 @@ class ZRText extends Displayable<TextProps> implements GroupLike {
619
652
 
620
653
  private _updateRichTexts() {
621
654
  const style = this.style;
655
+ const defaultStyle = this._defaultStyle;
656
+
657
+ const textAlign = style.align || defaultStyle.align;
658
+ const verticalAlign = style.verticalAlign || defaultStyle.verticalAlign;
659
+ let baseX = style.x || 0;
660
+ let baseY = style.y || 0;
661
+
662
+ calcInnerTextOverflowArea(
663
+ tmpCITOverflowAreaOut, defaultStyle.overflowRect, baseX, baseY, textAlign, verticalAlign
664
+ );
665
+ baseX = tmpCITOverflowAreaOut.baseX;
666
+ baseY = tmpCITOverflowAreaOut.baseY;
622
667
 
623
668
  // TODO Only parse when text changed?
624
669
  const text = getStyleText(style);
625
- const contentBlock = parseRichText(text, style);
670
+ const contentBlock = parseRichText(
671
+ text,
672
+ style,
673
+ tmpCITOverflowAreaOut.outerWidth,
674
+ tmpCITOverflowAreaOut.outerHeight,
675
+ textAlign
676
+ );
626
677
 
627
678
  const contentWidth = contentBlock.width;
628
679
  const outerWidth = contentBlock.outerWidth;
629
680
  const outerHeight = contentBlock.outerHeight;
630
681
  const textPadding = style.padding as number[];
631
682
 
632
- const baseX = style.x || 0;
633
- const baseY = style.y || 0;
634
- const defaultStyle = this._defaultStyle;
635
- const textAlign = style.align || defaultStyle.align;
636
- const verticalAlign = style.verticalAlign || defaultStyle.verticalAlign;
683
+ this.isTruncated = !!contentBlock.isTruncated;
637
684
 
638
685
  const boxX = adjustTextX(baseX, outerWidth, textAlign);
639
686
  const boxY = adjustTextY(baseY, outerHeight, verticalAlign);