Skip to content

6.0.0

Compare
Choose a tag to compare
@xiaoiver xiaoiver released this 21 Mar 08:33
· 47 commits to next since this release
86d200b

Breaking changes

The relative renderer and plugins should also be updated, eg.

Transform matrix should only be affected by transform attribute

In previous designs, many of the initial properties of the shapes will affect the Transform and the mat4 transform matrix behind it, for example:

  • cx/cy in Circle / Ellipse
  • x/y in Rect / Image / Group / CustomElement
  • d in Path
  • x1/y1/x2/y2 in Line
  • points in Polyline / Polygon

In fact, the transform matrix should only be controlled by the transform attribute, which leads to

  1. A lot of shapes that don't have a transform are computing the initial transform matrix, with unnecessary performance overhead and GC time
  2. some bugs caused by inconsistent transform sources. e.g. #1413 #1624
  3. SVG can't set the corresponding attribute directly (native SVG <group> doesn't have an x/y attribute), it needs additional operations.

So here's the breaking change looks like:

const circle = new Circle({ style: { cx: 100, cy: 100 } });

// before
circle.getPosition(); // [100, 100] `cx/cy` affect the transform matrix, whoops!!!
// after
circle.getPosition(); // [0, 0]

// Only transform attribute will affect RTS matrix.
circle.style.transform = 'translate(100, 100)';
circle.getPosition(); // [100, 100]

Example 1

Here's an example from G2, for a Path with the following attributes:

Path({ 
  d: 'M -134.98699951171875,-100.01200103759766....', 
  transform: 'translate(304, 210)'
})

Now the transform property can be visualized from the SVG dom:

after before

Example 2

We can create a following scenegraph Rect(parent) -> Rect(child) like this:

const parent = new Rect({
  style: {
    x: 100,
    y: 100,
    width: 200,
    height: 200,
    fill: '#1890FF',
  },
});
const child = new Rect({
  style: {
    x: 0,
    y: 0,
    width: 100,
    height: 100,
    fill: 'red',
  }
});
parent.appendChild(child);

We should see the following result at [email protected], the red child start drawing itself from parent's x/y:

scenegraph before

But now since x/y won't affect the parent's transform, the origin of local transform is still [0, 0]:

scenegraph after

Of course we can set the parent's transform and reset its x/y to [0, 0], at this point the effect is the same as before:

const parent = new Rect({
  style: {
    x: 0,
    y: 0,
    width: 200,
    height: 200,
    fill: '#1890FF',
    transform: 'translate(100, 100)'
  },
});

Scenegraph should only pass transform from top to bottom.

Example3

Now we can implement the official SVG transform-origin example:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform-origin

Code: https://github.com/antvis/G/blob/%40antv/g%406.0.0/__tests__/demos/2d/transform-origin.ts

x/y attribute is removed from Group and CustomElement

Native SVG <group> doesn't have an x/y attribute. Transformations applied to the <grroup> element are performed on its child elements.

// before
group.style.x = 100;
group.style.y = 100;

// after
group.style.transform = 'translate(100, 100)';

anchor attribute is removed

// before
rect.style.width = 100;
rect.style.height = 100;
rect.style.anchor = '0.5 0.5';

// after
rect.style.transform = 'translate(-50, -50)';

clipPath share the coordinates with its target

Now the clipPath and its target share the same local coordinates, which can solve some confusing problems before:

const clipPath = new Circle({
  style: {
    cx: 100,
    cy: 100,
    r: 50,
  },
});

const rect = new Rect({
  style: {
    x: 100
    y: 100,
    width: 100,
    height: 100,
    clipPath,
  }
});

Use more standardized attribute name

  • Must use d instead of path in Path.
  • Must use src instead of img in Image.
  • Must use lineWidth instead of strokeWidth
  • Must use lineDash instead of strokeDasharray
  • Must use textAlign instead of textAnchor

The default value of transformOrigin in Circle / Ellipse is no more center

You should set manually like this if you want to scale/rotate around the center:

const circle = new Circle({ style: { cx: 10, cy: 10 } });

circle.style.transformOrigin = 'center';
circle.style.transformOrigin = '10 10'; // faster because it don't need to calculate bounds.

remove get/setClip from DisplayObject

// before
const clipPath = circle.getClip();
circle.setClip(clipPath);

// after
const clipPath = circle.style.clipPath;
circle.style.clipPath = clipPath;

Other changes

enableCSSParsing is disabled by default

Which means you cannot use value with unit by default unless enable it.

runtime.enableCSSParsing = true;
circle.style.r = '3em';

enableAttributeDashCased is disabled by default

The built-in attributes can be accessed only when enableAttributeDashCased` is enabled.

runtime.enableAttributeDashCased = true;
circle.setAttribute('line-width', '2');

Performance

The online benchmarks: https://observablehq.com/d/d54e30062ec837a5

~2x perf boost compared with 5.x.

Delay the calculation of totalLength for Polyline

We found the process of parse points for Polyline is very time-consuming. The following image shows the processing time from G2.

image

Delay the calculation of BBox