G Versions Save

💥 A flexible rendering engine for visualization.

@antv/[email protected]

1 month ago

What's Changed

  • 6009d6f2: Scaled local time should not be interpolated with easing function.

Full Changelog: https://github.com/antvis/G/compare/@antv/[email protected]...@antv/[email protected]

@antv/[email protected]

1 month ago

What's Changed

Patch Changes

  • acabbcb0: Update Text's geometry before getting computed length.

@antv/[email protected]

1 month ago

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

@antv/[email protected]

1 month ago

Patch Changes

@antv/[email protected]

1 month ago

Patch Changes

@antv/[email protected]

3 months ago

Patch Changes

Disable memoize during interpolation to avoid OOM.

@antv/[email protected]

4 months ago

Patch Changes

@antv/[email protected]

5 months ago

Patch Changes

You can also register custom easing function via EasingFunctions like this:

import { EasingFunctions } from '@antv/g';

// Register easing function.
EasingFunctions['my-easing'] = (t: number) => t;

circle.animate([{ opacity: 0 }, { opacity: 1 }], {
  duration: 500,
  easing: 'my-easing', // Use it by name.
});

You can find more easing functions on: https://easings.net/

@antv/[email protected]

5 months ago

5.18.21

Patch Changes

  • Path should not downgrade to line when isBillboard enabled and fill should be used correctly.
  • willReadFrequently: true should be passed in when creating offscreen canvas so that the browser won't throw warning.

@antv/[email protected]

5 months ago

Patch Changes

  • 4fdee19f: Keep aspect ratio in image.

OnlineExample

When keepAspectRatio enabled, either width or height can be omitted and the missing one can be inferred according to raw image's aspect. In the following example, height will be calculated automatically after the Image being loaded.

new Image({
  style: {
    src: 'http://',
    keepAspectRatio: true,
    width: 100
  }
})

But since the image loading process is in an async way, if we try to get bounds immediately, we'll get an empty bounds:

const image = new Image({
  style: {
    src: 'http://',
    keepAspectRatio: true,
    width: 100
  }
});
image.getBounds(); // empty