Skip to content

Commit

Permalink
fix: set transform-origin in each keyframe (#5679)
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed Oct 24, 2023
1 parent b511b27 commit c49cf09
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 69 deletions.
50 changes: 50 additions & 0 deletions __tests__/integration/animation-control.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Canvas } from '@antv/g';
import { osAreaStackEnter } from '../plots/animation/os-area-stack-enter';
import { G2Context } from '../../src';
import { renderSpec } from './utils/renderSpec';
import './utils/useSnapshotMatchers';
import './utils/useCustomFetch';
import { sleep } from './utils/sleep';

describe('context.animations', () => {
let canvas: Canvas;
it('go to specific timestamp in animations', async () => {
const context: G2Context = {};
canvas = await renderSpec(osAreaStackEnter, context);

const goto = async (currentTime: number) => {
context.animations?.forEach((animation) => {
animation.pause();
animation.currentTime = currentTime;
});
await sleep(300);
};

const finish = async () => {
context.animations?.forEach((animation) => {
animation.finish();
});
await sleep(300);
};

goto(1);

const dir = `${__dirname}/snapshots/animation/control`;
const intervals = [0, 1000, 5000];
for (let i = 0; i < intervals.length; i++) {
const currentTime = intervals[i];
await goto(currentTime);
await expect(context.canvas).toMatchCanvasSnapshot(dir, `interval${i}`);
}

await finish();
await expect(context.canvas).toMatchCanvasSnapshot(
dir,
`interval${intervals.length}`,
);
});

afterAll(() => {
canvas?.destroy();
});
});
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 1 addition & 6 deletions src/animation/growInX.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IAnimation, Path } from '@antv/g';
import { Path } from '@antv/g';
import { AnimationComponent as AC } from '../runtime';
import { Animation } from './types';
import { ScaleInX } from './scaleInX';
Expand All @@ -22,11 +22,6 @@ export const GrowInX: AC<GrowInXOptions> = (options, context) => {

const animation = ScaleInX(options, context)([clipPath], to, defaults);

(animation as IAnimation).finished.then(() => {
clipPath.remove();
shape.style.clipPath = null;
});

return animation;
};
};
Expand Down
7 changes: 1 addition & 6 deletions src/animation/growInY.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IAnimation, Path } from '@antv/g';
import { Path } from '@antv/g';
import { AnimationComponent as AC } from '../runtime';
import { Animation } from './types';
import { ScaleInY } from './scaleInY';
Expand All @@ -22,11 +22,6 @@ export const GrowInY: AC<GrowInYOptions> = (options, context) => {

const animation = ScaleInY(options, context)([clipPath], to, defaults);

(animation as IAnimation).finished.then(() => {
clipPath.remove();
shape.style.clipPath = null;
});

return animation;
};
};
Expand Down
19 changes: 8 additions & 11 deletions src/animation/scaleInX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,47 @@ export const ScaleInX: AC<ScaleInXOptions> = (options, context) => {

return (from, _, defaults) => {
const [shape] = from;
const { height } = shape.getBoundingClientRect();
const {
transform: prefix = '',
fillOpacity = 1,
strokeOpacity = 1,
opacity = 1,
} = shape.style;
const [transformOrigin, transform]: [[number, number], string] =
isTranspose(coordinate)
? [[0, height], `scale(1, ${ZERO})`] // left-bottom corner
: [[0, 0], `scale(${ZERO}, 1)`]; // left-top corner
const [transformOrigin, transform]: [string, string] = isTranspose(
coordinate,
)
? [`left bottom`, `scale(1, ${ZERO})`] // left-bottom corner
: [`left top`, `scale(${ZERO}, 1)`]; // left-top corner

// Using a short fadeIn transition to hide element with scale(0.001)
// which is still visible.
const keyframes = [
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity: 0,
strokeOpacity: 0,
opacity: 0,
},
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
offset: 0.01,
},
{
transform: `${prefix} scale(1, 1)`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
},
];

// Change transform origin for correct transform.
shape.setOrigin(transformOrigin);

const animation = shape.animate(keyframes, { ...defaults, ...options });

// Reset transform origin to eliminate side effect for following animations.
animation.finished.then(() => shape.setOrigin(0, 0));

return animation;
};
};
19 changes: 8 additions & 11 deletions src/animation/scaleInY.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,47 @@ export const ScaleInY: AC<ScaleInYOptions> = (options, context) => {

return (from, _, defaults) => {
const [shape] = from;
const { height } = shape.getBoundingClientRect();
const {
transform: prefix = '',
fillOpacity = 1,
strokeOpacity = 1,
opacity = 1,
} = shape.style;
const [transformOrigin, transform]: [[number, number], string] =
isTranspose(coordinate)
? [[0, 0], `scale(${ZERO}, 1)`] // left-top corner
: [[0, height], `scale(1, ${ZERO})`]; // left-bottom corner
const [transformOrigin, transform]: [string, string] = isTranspose(
coordinate,
)
? [`left top`, `scale(${ZERO}, 1)`] // left-top corner
: [`left bottom`, `scale(1, ${ZERO})`]; // left-bottom corner

// Using a short fadeIn transition to hide element with scale(0.001)
// which is still visible.
const keyframes = [
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity: 0,
strokeOpacity: 0,
opacity: 0,
},
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
offset: 0.01,
},
{
transform: `${prefix} scale(1, 1)`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
},
];

// Change transform origin for correct transform.
shape.setOrigin(transformOrigin);

const animation = shape.animate(keyframes, { ...defaults, ...options });

// Reset transform origin to eliminate side effect for following animations.
animation.finished.then(() => shape.setOrigin(0, 0));

return animation;
};
};
19 changes: 8 additions & 11 deletions src/animation/scaleOutX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,44 @@ export const ScaleOutX: AC<ScaleOutXOptions> = (options, context) => {

return (from, _, defaults) => {
const [shape] = from;
const { height } = shape.getBoundingClientRect();
const {
transform: prefix = '',
fillOpacity = 1,
strokeOpacity = 1,
opacity = 1,
} = shape.style;
const [transformOrigin, transform]: [[number, number], string] =
isTranspose(coordinate)
? [[0, height], `scale(1, ${ZERO})`] // left-bottom corner
: [[0, 0], `scale(${ZERO}, 1)`]; // left-top corner
const [transformOrigin, transform]: [string, string] = isTranspose(
coordinate,
)
? [`left bottom`, `scale(1, ${ZERO})`] // left-bottom corner
: [`left top`, `scale(${ZERO}, 1)`]; // left-top corner

// Using a short fadeIn transition to hide element with scale(0.001)
// which is still visible.
const keyframes = [
{
transform: `${prefix} scale(1, 1)`.trimStart(),
transformOrigin,
},
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
offset: 0.99,
},
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity: 0,
strokeOpacity: 0,
opacity: 0,
},
];

// Change transform origin for correct transform.
shape.setOrigin(transformOrigin);

const animation = shape.animate(keyframes, { ...defaults, ...options });

// Reset transform origin to eliminate side effect for following animations.
animation.finished.then(() => shape.setOrigin(0, 0));

return animation;
};
};
19 changes: 8 additions & 11 deletions src/animation/scaleOutY.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,44 @@ export const ScaleOutY: AC<ScaleOutYOptions> = (options, context) => {

return (from, _, defaults) => {
const [shape] = from;
const { height } = shape.getBoundingClientRect();
const {
transform: prefix = '',
fillOpacity = 1,
strokeOpacity = 1,
opacity = 1,
} = shape.style;
const [transformOrigin, transform]: [[number, number], string] =
isTranspose(coordinate)
? [[0, 0], `scale(${ZERO}, 1)`] // left-top corner
: [[0, height], `scale(1, ${ZERO})`]; // left-bottom corner
const [transformOrigin, transform]: [string, string] = isTranspose(
coordinate,
)
? [`left top`, `scale(${ZERO}, 1)`] // left-top corner
: [`left bottom`, `scale(1, ${ZERO})`]; // left-bottom corner

// Using a short fadeIn transition to hide element with scale(0.001)
// which is still visible.
const keyframes = [
{
transform: `${prefix} scale(1, 1)`.trimStart(),
transformOrigin,
},
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
offset: 0.99,
},
{
transform: `${prefix} ${transform}`.trimStart(),
transformOrigin,
fillOpacity: 0,
strokeOpacity: 0,
opacity: 0,
},
];

// Change transform origin for correct transform.
shape.setOrigin(transformOrigin);

const animation = shape.animate(keyframes, { ...defaults, ...options });

// Reset transform origin to eliminate side effect for following animations.
animation.finished.then(() => shape.setOrigin(0, 0));

return animation;
};
};
10 changes: 4 additions & 6 deletions src/animation/zoomIn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,34 @@ export const ZoomIn: AC<ZoomInOptions> = (options) => {
strokeOpacity = 1,
opacity = 1,
} = shape.style;
const transformOrigin = 'center center';
const keyframes = [
{
transform: `${prefix} scale(${ZERO})`.trimStart(),
transformOrigin,
fillOpacity: 0,
strokeOpacity: 0,
opacity: 0,
},
{
transform: `${prefix} scale(${ZERO})`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
offset: 0.01,
},
{
transform: `${prefix} scale(1)`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
},
];
const { width, height } = shape.getBoundingClientRect();
// Change transform origin for correct transform.
shape.setOrigin([width / 2, height / 2]);

const animation = shape.animate(keyframes, { ...defaults, ...options });

// Reset transform origin to eliminate side effect for following animations.
animation.finished.then(() => shape.setOrigin(0, 0));

return animation;
};
};
11 changes: 4 additions & 7 deletions src/animation/zoomOut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,28 @@ export const ZoomOut: AC<ZoomOutOptions> = (options) => {
strokeOpacity = 1,
opacity = 1,
} = shape.style;
const transformOrigin = 'center center';
const keyframes = [
{ transform: `${prefix} scale(1)`.trimStart() },
{ transform: `${prefix} scale(1)`.trimStart(), transformOrigin },
{
transform: `${prefix} scale(${ZERO})`.trimStart(),
transformOrigin,
fillOpacity,
strokeOpacity,
opacity,
offset: 0.99,
},
{
transform: `${prefix} scale(${ZERO})`.trimStart(),
transformOrigin,
fillOpacity: 0,
strokeOpacity: 0,
opacity: 0,
},
];

const { width, height } = shape.getBoundingClientRect();
// Change transform origin for correct transform.
shape.setOrigin([width / 2, height / 2]);
const animation = shape.animate(keyframes, { ...defaults, ...options });

// Reset transform origin to eliminate side effect for following animations.
animation.finished.then(() => shape.setOrigin(0, 0));

return animation;
};
};

0 comments on commit c49cf09

Please sign in to comment.