zrender-nightly 5.5.0-dev.20240131 → 5.5.1-dev.20240131

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/package.json +3 -0
  3. package/dist/package.json +3 -0
  4. package/dist/zrender.js +218 -27
  5. package/dist/zrender.js.map +1 -1
  6. package/dist/zrender.min.js +1 -1
  7. package/lib/Element.d.ts +1 -0
  8. package/lib/Element.js +12 -0
  9. package/lib/Handler.js +3 -3
  10. package/lib/canvas/Layer.d.ts +0 -1
  11. package/lib/canvas/Layer.js +2 -2
  12. package/lib/canvas/Painter.js +1 -1
  13. package/lib/core/PathProxy.js +0 -1
  14. package/lib/core/Transformable.js +5 -1
  15. package/lib/core/env.js +2 -1
  16. package/lib/core/matrix.d.ts +1 -1
  17. package/lib/core/matrix.js +4 -3
  18. package/lib/core/timsort.js +0 -9
  19. package/lib/graphic/helper/parseText.d.ts +1 -1
  20. package/lib/svg/Painter.d.ts +2 -0
  21. package/lib/svg/Painter.js +3 -2
  22. package/lib/svg/core.d.ts +3 -1
  23. package/lib/svg/core.js +2 -1
  24. package/lib/svg/cssAnimation.js +2 -1
  25. package/lib/svg/cssClassId.d.ts +1 -0
  26. package/lib/svg/cssClassId.js +4 -0
  27. package/lib/svg/cssEmphasis.d.ts +3 -0
  28. package/lib/svg/cssEmphasis.js +60 -0
  29. package/lib/svg/graphic.js +21 -1
  30. package/lib/svg/patch.js +4 -1
  31. package/lib/tool/color.d.ts +3 -0
  32. package/lib/tool/color.js +21 -0
  33. package/lib/tool/parseSVG.js +4 -1
  34. package/lib/zrender.d.ts +10 -4
  35. package/lib/zrender.js +69 -6
  36. package/package.README.md +9 -0
  37. package/package.json +29 -2
  38. package/src/.eslintrc.yaml +1 -1
  39. package/src/Element.ts +16 -0
  40. package/src/Handler.ts +3 -3
  41. package/src/canvas/Layer.ts +2 -5
  42. package/src/canvas/Painter.ts +2 -2
  43. package/src/core/PathProxy.ts +0 -2
  44. package/src/core/Transformable.ts +6 -1
  45. package/src/core/env.ts +4 -1
  46. package/src/core/matrix.ts +8 -3
  47. package/src/core/timsort.ts +0 -13
  48. package/src/core/util.ts +4 -4
  49. package/src/dom/HandlerProxy.ts +7 -7
  50. package/src/graphic/helper/parseText.ts +4 -4
  51. package/src/svg/Painter.ts +13 -6
  52. package/src/svg/core.ts +10 -2
  53. package/src/svg/cssAnimation.ts +2 -1
  54. package/src/svg/cssClassId.ts +5 -0
  55. package/src/svg/cssEmphasis.ts +73 -0
  56. package/src/svg/graphic.ts +23 -1
  57. package/src/svg/patch.ts +5 -2
  58. package/src/tool/color.ts +27 -1
  59. package/src/tool/parseSVG.ts +4 -1
  60. package/src/zrender.ts +82 -11
  61. package/.travis.yml +0 -12
@@ -10,6 +10,7 @@ import Animator from '../animation/Animator';
10
10
  import CompoundPath from '../graphic/CompoundPath';
11
11
  import { AnimationEasing } from '../animation/easing';
12
12
  import { createCubicEasingFunc } from '../animation/cubicEasing';
13
+ import { getClassId } from './cssClassId';
13
14
 
14
15
  export const EASING_MAP: Record<string, string> = {
15
16
  // From https://easings.net/
@@ -355,7 +356,7 @@ export function createCSSAnimation(
355
356
  }
356
357
 
357
358
  if (cssAnimations.length) {
358
- const className = scope.zrId + '-cls-' + scope.cssClassIdx++;
359
+ const className = scope.zrId + '-cls-' + getClassId();
359
360
  scope.cssNodes['.' + className] = {
360
361
  animation: cssAnimations.join(',')
361
362
  };
@@ -0,0 +1,5 @@
1
+ let cssClassIdx = 0;
2
+
3
+ export function getClassId() {
4
+ return cssClassIdx++;
5
+ }
@@ -0,0 +1,73 @@
1
+ import Displayable from '../graphic/Displayable';
2
+ import { liftColor } from '../tool/color';
3
+ import { BrushScope, SVGVNodeAttrs } from './core';
4
+ import { getClassId } from './cssClassId';
5
+
6
+ export function createCSSEmphasis(
7
+ el: Displayable,
8
+ attrs: SVGVNodeAttrs,
9
+ scope: BrushScope
10
+ ) {
11
+ if (!el.ignore) {
12
+ if (el.isSilent()) {
13
+ // If el is silent, it can not be hovered nor selected.
14
+ // So set pointer-events to pass through.
15
+ const style = {
16
+ 'pointer-events': 'none'
17
+ };
18
+ setClassAttribute(style, attrs, scope, true);
19
+ }
20
+ else {
21
+ const emphasisStyle = el.states.emphasis && el.states.emphasis.style
22
+ ? el.states.emphasis.style
23
+ : {};
24
+ let fill = emphasisStyle.fill;
25
+ if (!fill) {
26
+ // No empahsis fill, lift color
27
+ const normalFill = el.style && el.style.fill;
28
+ const selectFill = el.states.select
29
+ && el.states.select.style
30
+ && el.states.select.style.fill;
31
+ const fromFill = el.currentStates.indexOf('select') >= 0
32
+ ? (selectFill || normalFill)
33
+ : normalFill;
34
+ if (fromFill) {
35
+ fill = liftColor(fromFill);
36
+ }
37
+ }
38
+ let lineWidth = emphasisStyle.lineWidth;
39
+ if (lineWidth) {
40
+ // Symbols use transform to set size, so lineWidth
41
+ // should be divided by scaleX
42
+ const scaleX = (!emphasisStyle.strokeNoScale && el.transform)
43
+ ? el.transform[0]
44
+ : 1;
45
+ lineWidth = lineWidth / scaleX;
46
+ }
47
+ const style = {
48
+ cursor: 'pointer', // TODO: Should this be customized?
49
+ } as any;
50
+ if (fill) {
51
+ style.fill = fill;
52
+ }
53
+ if (emphasisStyle.stroke) {
54
+ style.stroke = emphasisStyle.stroke;
55
+ }
56
+ if (lineWidth) {
57
+ style['stroke-width'] = lineWidth;
58
+ }
59
+ setClassAttribute(style, attrs, scope, true);
60
+ }
61
+ }
62
+ }
63
+
64
+ function setClassAttribute(style: object, attrs: SVGVNodeAttrs, scope: BrushScope, withHover: boolean) {
65
+ const styleKey = JSON.stringify(style);
66
+ let className = scope.cssStyleCache[styleKey];
67
+ if (!className) {
68
+ className = scope.zrId + '-cls-' + getClassId();
69
+ scope.cssStyleCache[styleKey] = className;
70
+ scope.cssNodes['.' + className + (withHover ? ':hover' : '')] = style as any;
71
+ }
72
+ attrs.class = attrs.class ? (attrs.class + ' ' + className) : className;
73
+ }
@@ -26,7 +26,7 @@ import { getLineHeight } from '../contain/text';
26
26
  import TSpan, { TSpanStyleProps } from '../graphic/TSpan';
27
27
  import SVGPathRebuilder from './SVGPathRebuilder';
28
28
  import mapStyleToAttrs from './mapStyleToAttrs';
29
- import { SVGVNodeAttrs, createVNode, SVGVNode, vNodeToString, BrushScope } from './core';
29
+ import { SVGVNodeAttrs, createVNode, SVGVNode, vNodeToString, BrushScope, META_DATA_PREFIX } from './core';
30
30
  import { MatrixArray } from '../core/matrix';
31
31
  import Displayable from '../graphic/Displayable';
32
32
  import { assert, clone, isFunction, isString, logError, map, retrieve2 } from '../core/util';
@@ -39,6 +39,8 @@ import { ImageLike } from '../core/types';
39
39
  import { createCSSAnimation } from './cssAnimation';
40
40
  import { hasSeparateFont, parseFontSize } from '../graphic/Text';
41
41
  import { DEFAULT_FONT, DEFAULT_FONT_FAMILY } from '../core/platform';
42
+ import { createCSSEmphasis } from './cssEmphasis';
43
+ import { getElementSSRData } from '../zrender';
42
44
 
43
45
  const round = Math.round;
44
46
 
@@ -61,6 +63,10 @@ function setStyleAttrs(attrs: SVGVNodeAttrs, style: AllStyleOption, el: Path | T
61
63
  else if (isFillStroke && isPattern(val)) {
62
64
  setPattern(el, attrs, key, scope);
63
65
  }
66
+ else if (isFillStroke && val === 'none') {
67
+ // When is none, it cannot be interacted when ssr
68
+ attrs[key] = 'transparent';
69
+ }
64
70
  else {
65
71
  attrs[key] = val;
66
72
  }
@@ -69,6 +75,18 @@ function setStyleAttrs(attrs: SVGVNodeAttrs, style: AllStyleOption, el: Path | T
69
75
  setShadow(el, attrs, scope);
70
76
  }
71
77
 
78
+ function setMetaData(attrs: SVGVNodeAttrs, el: Path | TSpan | ZRImage) {
79
+ const metaData = getElementSSRData(el);
80
+ if (metaData) {
81
+ metaData.each((val, key) => {
82
+ val != null && (attrs[(META_DATA_PREFIX + key).toLowerCase()] = val + '');
83
+ });
84
+ if (el.isSilent()) {
85
+ attrs[META_DATA_PREFIX + 'silent'] = 'true';
86
+ }
87
+ }
88
+ }
89
+
72
90
  function noRotateScale(m: MatrixArray) {
73
91
  return isAroundZero(m[0] - 1)
74
92
  && isAroundZero(m[1])
@@ -204,8 +222,10 @@ export function brushSVGPath(el: Path, scope: BrushScope) {
204
222
 
205
223
  setTransform(attrs, el.transform);
206
224
  setStyleAttrs(attrs, style, el, scope);
225
+ setMetaData(attrs, el);
207
226
 
208
227
  scope.animation && createCSSAnimation(el, attrs, scope);
228
+ scope.emphasis && createCSSEmphasis(el, attrs, scope);
209
229
 
210
230
  return createVNode(svgElType, el.id + '', attrs);
211
231
  }
@@ -248,6 +268,7 @@ export function brushSVGImage(el: ZRImage, scope: BrushScope) {
248
268
 
249
269
  setTransform(attrs, el.transform);
250
270
  setStyleAttrs(attrs, style, el, scope);
271
+ setMetaData(attrs, el);
251
272
 
252
273
  scope.animation && createCSSAnimation(el, attrs, scope);
253
274
 
@@ -319,6 +340,7 @@ export function brushSVGTSpan(el: TSpan, scope: BrushScope) {
319
340
  }
320
341
  setTransform(attrs, el.transform);
321
342
  setStyleAttrs(attrs, style, el, scope);
343
+ setMetaData(attrs, el);
322
344
 
323
345
  scope.animation && createCSSAnimation(el, attrs, scope);
324
346
 
package/src/svg/patch.ts CHANGED
@@ -122,7 +122,7 @@ function removeVnodes(parentElm: Node, vnodes: SVGVNode[], startIdx: number, end
122
122
 
123
123
  export function updateAttrs(oldVnode: SVGVNode, vnode: SVGVNode): void {
124
124
  let key: string;
125
- const elm = vnode.elm as Element;
125
+ const elm = vnode.elm as SVGElement;
126
126
  const oldAttrs = oldVnode && oldVnode.attrs || {};
127
127
  const attrs = vnode.attrs || {};
128
128
 
@@ -143,7 +143,10 @@ export function updateAttrs(oldVnode: SVGVNode, vnode: SVGVNode): void {
143
143
  elm.removeAttribute(key);
144
144
  }
145
145
  else {
146
- if (key.charCodeAt(0) !== xChar) {
146
+ if (key === 'style') {
147
+ elm.style.cssText = cur as string;
148
+ }
149
+ else if (key.charCodeAt(0) !== xChar) {
147
150
  elm.setAttribute(key, cur as any);
148
151
  }
149
152
  // TODO
package/src/tool/color.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import LRU from '../core/LRU';
2
+ import { extend, isGradientObject, isString, map } from '../core/util';
3
+ import { GradientObject } from '../graphic/Gradient';
2
4
 
3
5
  const kCSSColorTable = {
4
6
  'transparent': [0, 0, 0, 0], 'aliceblue': [240, 248, 255, 1],
@@ -566,4 +568,28 @@ export function random(): string {
566
568
  Math.round(Math.random() * 255),
567
569
  Math.round(Math.random() * 255)
568
570
  ], 'rgb');
569
- }
571
+ }
572
+
573
+ const liftedColorCache = new LRU<string>(100);
574
+ export function liftColor(color: GradientObject): GradientObject;
575
+ export function liftColor(color: string): string;
576
+ export function liftColor(color: string | GradientObject): string | GradientObject {
577
+ if (isString(color)) {
578
+ let liftedColor = liftedColorCache.get(color);
579
+ if (!liftedColor) {
580
+ liftedColor = lift(color, -0.1);
581
+ liftedColorCache.put(color, liftedColor);
582
+ }
583
+ return liftedColor;
584
+ }
585
+ else if (isGradientObject(color)) {
586
+ const ret = extend({}, color) as GradientObject;
587
+ ret.colorStops = map(color.colorStops, stop => ({
588
+ offset: stop.offset,
589
+ color: lift(stop.color, -0.1)
590
+ }));
591
+ return ret;
592
+ }
593
+ // Change nothing.
594
+ return color;
595
+ }
@@ -845,7 +845,10 @@ function parseTransformAttribute(xmlNode: SVGElement, node: Element): void {
845
845
  break;
846
846
  case 'rotate':
847
847
  // TODO: zrender use different hand in coordinate system.
848
- matrix.rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
848
+ matrix.rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE, [
849
+ parseFloat(valueArr[1] || '0'),
850
+ parseFloat(valueArr[2] || '0')
851
+ ]);
849
852
  break;
850
853
  case 'skewX':
851
854
  const sx = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
package/src/zrender.ts CHANGED
@@ -81,7 +81,7 @@ class ZRender {
81
81
 
82
82
  private _needsRefresh = true
83
83
  private _needsRefreshHover = true
84
-
84
+ private _disposed: boolean;
85
85
  /**
86
86
  * If theme is dark mode. It will determine the color strategy for labels.
87
87
  */
@@ -123,7 +123,7 @@ class ZRender {
123
123
  this.storage = storage;
124
124
  this.painter = painter;
125
125
 
126
- const handerProxy = (!env.node && !env.worker && !ssrMode)
126
+ const handlerProxy = (!env.node && !env.worker && !ssrMode)
127
127
  ? new HandlerProxy(painter.getViewportRoot(), painter.root)
128
128
  : null;
129
129
 
@@ -137,7 +137,7 @@ class ZRender {
137
137
  pointerSize = zrUtil.retrieve2(opts.pointerSize, defaultPointerSize);
138
138
  }
139
139
 
140
- this.handler = new Handler(storage, painter, handerProxy, painter.root, pointerSize);
140
+ this.handler = new Handler(storage, painter, handlerProxy, painter.root, pointerSize);
141
141
 
142
142
  this.animation = new Animation({
143
143
  stage: {
@@ -154,7 +154,7 @@ class ZRender {
154
154
  * 添加元素
155
155
  */
156
156
  add(el: Element) {
157
- if (!el) {
157
+ if (this._disposed || !el) {
158
158
  return;
159
159
  }
160
160
  this.storage.addRoot(el);
@@ -166,7 +166,7 @@ class ZRender {
166
166
  * 删除元素
167
167
  */
168
168
  remove(el: Element) {
169
- if (!el) {
169
+ if (this._disposed || !el) {
170
170
  return;
171
171
  }
172
172
  this.storage.delRoot(el);
@@ -178,6 +178,9 @@ class ZRender {
178
178
  * Change configuration of layer
179
179
  */
180
180
  configLayer(zLevel: number, config: LayerConfig) {
181
+ if (this._disposed) {
182
+ return;
183
+ }
181
184
  if (this.painter.configLayer) {
182
185
  this.painter.configLayer(zLevel, config);
183
186
  }
@@ -188,6 +191,9 @@ class ZRender {
188
191
  * Set background color
189
192
  */
190
193
  setBackgroundColor(backgroundColor: string | GradientObject | PatternObject) {
194
+ if (this._disposed) {
195
+ return;
196
+ }
191
197
  if (this.painter.setBackgroundColor) {
192
198
  this.painter.setBackgroundColor(backgroundColor);
193
199
  }
@@ -215,6 +221,9 @@ class ZRender {
215
221
  * Repaint the canvas immediately
216
222
  */
217
223
  refreshImmediately(fromInside?: boolean) {
224
+ if (this._disposed) {
225
+ return;
226
+ }
218
227
  // const start = new Date();
219
228
  if (!fromInside) {
220
229
  // Update animation if refreshImmediately is invoked from outside.
@@ -234,6 +243,9 @@ class ZRender {
234
243
  * Mark and repaint the canvas in the next frame of browser
235
244
  */
236
245
  refresh() {
246
+ if (this._disposed) {
247
+ return;
248
+ }
237
249
  this._needsRefresh = true;
238
250
  // Active the animation again.
239
251
  this.animation.start();
@@ -243,6 +255,9 @@ class ZRender {
243
255
  * Perform all refresh
244
256
  */
245
257
  flush() {
258
+ if (this._disposed) {
259
+ return;
260
+ }
246
261
  this._flush(false);
247
262
  }
248
263
 
@@ -269,7 +284,7 @@ class ZRender {
269
284
  }
270
285
  else if (this._sleepAfterStill > 0) {
271
286
  this._stillFrameAccum++;
272
- // Stop the animiation after still for 10 frames.
287
+ // Stop the animation after still for 10 frames.
273
288
  if (this._stillFrameAccum > this._sleepAfterStill) {
274
289
  this.animation.stop();
275
290
  }
@@ -288,6 +303,9 @@ class ZRender {
288
303
  * Wake up animation loop. But not render.
289
304
  */
290
305
  wakeUp() {
306
+ if (this._disposed) {
307
+ return;
308
+ }
291
309
  this.animation.start();
292
310
  // Reset the frame count.
293
311
  this._stillFrameAccum = 0;
@@ -304,6 +322,9 @@ class ZRender {
304
322
  * Refresh hover immediately
305
323
  */
306
324
  refreshHoverImmediately() {
325
+ if (this._disposed) {
326
+ return;
327
+ }
307
328
  this._needsRefreshHover = false;
308
329
  if (this.painter.refreshHover && this.painter.getType() === 'canvas') {
309
330
  this.painter.refreshHover();
@@ -318,6 +339,9 @@ class ZRender {
318
339
  width?: number| string
319
340
  height?: number | string
320
341
  }) {
342
+ if (this._disposed) {
343
+ return;
344
+ }
321
345
  opts = opts || {};
322
346
  this.painter.resize(opts.width, opts.height);
323
347
  this.handler.resize();
@@ -327,20 +351,29 @@ class ZRender {
327
351
  * Stop and clear all animation immediately
328
352
  */
329
353
  clearAnimation() {
354
+ if (this._disposed) {
355
+ return;
356
+ }
330
357
  this.animation.clear();
331
358
  }
332
359
 
333
360
  /**
334
361
  * Get container width
335
362
  */
336
- getWidth(): number {
363
+ getWidth(): number | undefined {
364
+ if (this._disposed) {
365
+ return;
366
+ }
337
367
  return this.painter.getWidth();
338
368
  }
339
369
 
340
370
  /**
341
371
  * Get container height
342
372
  */
343
- getHeight(): number {
373
+ getHeight(): number | undefined {
374
+ if (this._disposed) {
375
+ return;
376
+ }
344
377
  return this.painter.getHeight();
345
378
  }
346
379
 
@@ -349,6 +382,9 @@ class ZRender {
349
382
  * @param cursorStyle='default' 例如 crosshair
350
383
  */
351
384
  setCursorStyle(cursorStyle: string) {
385
+ if (this._disposed) {
386
+ return;
387
+ }
352
388
  this.handler.setCursorStyle(cursorStyle);
353
389
  }
354
390
 
@@ -361,7 +397,10 @@ class ZRender {
361
397
  findHover(x: number, y: number): {
362
398
  target: Displayable
363
399
  topTarget: Displayable
364
- } {
400
+ } | undefined {
401
+ if (this._disposed) {
402
+ return;
403
+ }
365
404
  return this.handler.findHover(x, y);
366
405
  }
367
406
 
@@ -370,7 +409,9 @@ class ZRender {
370
409
  on<Ctx>(eventName: string, eventHandler: WithThisType<EventCallback<any[]>, unknown extends Ctx ? ZRenderType : Ctx>, context?: Ctx): this
371
410
  // eslint-disable-next-line max-len
372
411
  on<Ctx>(eventName: string, eventHandler: (...args: any) => any, context?: Ctx): this {
373
- this.handler.on(eventName, eventHandler, context);
412
+ if (!this._disposed) {
413
+ this.handler.on(eventName, eventHandler, context);
414
+ }
374
415
  return this;
375
416
  }
376
417
 
@@ -381,6 +422,9 @@ class ZRender {
381
422
  */
382
423
  // eslint-disable-next-line max-len
383
424
  off(eventName?: string, eventHandler?: EventCallback) {
425
+ if (this._disposed) {
426
+ return;
427
+ }
384
428
  this.handler.off(eventName, eventHandler);
385
429
  }
386
430
 
@@ -391,6 +435,9 @@ class ZRender {
391
435
  * @param event Event object
392
436
  */
393
437
  trigger(eventName: string, event?: unknown) {
438
+ if (this._disposed) {
439
+ return;
440
+ }
394
441
  this.handler.trigger(eventName, event);
395
442
  }
396
443
 
@@ -399,6 +446,9 @@ class ZRender {
399
446
  * Clear all objects and the canvas.
400
447
  */
401
448
  clear() {
449
+ if (this._disposed) {
450
+ return;
451
+ }
402
452
  const roots = this.storage.getRoots();
403
453
  for (let i = 0; i < roots.length; i++) {
404
454
  if (roots[i] instanceof Group) {
@@ -413,6 +463,10 @@ class ZRender {
413
463
  * Dispose self.
414
464
  */
415
465
  dispose() {
466
+ if (this._disposed) {
467
+ return;
468
+ }
469
+
416
470
  this.animation.stop();
417
471
 
418
472
  this.clear();
@@ -425,6 +479,8 @@ class ZRender {
425
479
  this.painter =
426
480
  this.handler = null;
427
481
 
482
+ this._disposed = true;
483
+
428
484
  delInstance(this.id);
429
485
  }
430
486
  }
@@ -482,10 +538,25 @@ export function registerPainter(name: string, Ctor: PainterBaseCtor) {
482
538
  painterCtors[name] = Ctor;
483
539
  }
484
540
 
541
+ export type ElementSSRData = zrUtil.HashMap<unknown>;
542
+ export type ElementSSRDataGetter<T> = (el: Element) => zrUtil.HashMap<T>;
543
+
544
+ let ssrDataGetter: ElementSSRDataGetter<unknown>;
545
+
546
+ export function getElementSSRData(el: Element): ElementSSRData {
547
+ if (typeof ssrDataGetter === 'function') {
548
+ return ssrDataGetter(el);
549
+ }
550
+ }
551
+
552
+ export function registerSSRDataGetter<T>(getter: ElementSSRDataGetter<T>) {
553
+ ssrDataGetter = getter;
554
+ }
555
+
485
556
  /**
486
557
  * @type {string}
487
558
  */
488
- export const version = '5.5.0-dev.20240131';
559
+ export const version = '5.5.1-dev.20240131';
489
560
 
490
561
 
491
562
  export interface ZRenderType extends ZRender {};
package/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- language: node_js
2
-
3
- node_js:
4
- - "node"
5
-
6
- branches:
7
- only:
8
- - next
9
-
10
- script:
11
- - npm i
12
- - npm run build