Skip to content

Commit

Permalink
feat(lottie): support fill option when creating animation #1232
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed Dec 1, 2022
1 parent 5a6a3bb commit ea3560f
Show file tree
Hide file tree
Showing 8 changed files with 926 additions and 5 deletions.
4 changes: 4 additions & 0 deletions packages/g-lottie-player/src/LottieAnimation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,15 @@ export class LottieAnimation {
const formattedKeyframes = keyframes.map((keyframe) =>
definedProps(keyframe),
) as KeyframeAnimationKeyframe[];

console.log(this.context.fill);

const options = definedProps({
delay,
duration,
easing,
iterations: this.context.iterations,
fill: this.context.fill,
}) as Omit<KeyframeAnimation, 'keyframes'>;

keyframesOptions.push([formattedKeyframes, options]);
Expand Down
5 changes: 5 additions & 0 deletions packages/g-lottie-player/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export interface LoadAnimationOptions {
* @see https://github.com/airbnb/lottie-web/blob/master/player/js/animation/AnimationItem.js#L42
*/
autoplay: boolean;

/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/fill
*/
fill: FillMode;
}

/**
Expand Down
17 changes: 12 additions & 5 deletions packages/g-lottie-player/src/parser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class ParseContext {
endFrame: number;
version: string;
autoplay = false;
fill: FillMode = 'auto';
iterations = 0;

assetsMap: Map<string, Lottie.Asset> = new Map();
Expand Down Expand Up @@ -1203,15 +1204,20 @@ function parseLayers(
});
}

const DEFAULT_LOAD_ANIMATION_OPTIONS: LoadAnimationOptions = {
loop: true,
autoplay: false,
fill: 'both',
};
export function parse(
data: Lottie.Animation,
options: Partial<LoadAnimationOptions> = {
loop: true,
autoplay: false,
},
options: Partial<LoadAnimationOptions>,
) {
completeData(data);
const { loop, autoplay } = options;
const { loop, autoplay, fill } = {
...DEFAULT_LOAD_ANIMATION_OPTIONS,
...options,
};
const context = new ParseContext();

context.fps = data.fr || 30;
Expand All @@ -1220,6 +1226,7 @@ export function parse(
context.endFrame = data.op;
context.version = data.v;
context.autoplay = !!autoplay;
context.fill = fill;
context.iterations = isNumber(loop) ? loop : loop ? Infinity : 1;
// @see https://lottiefiles.github.io/lottie-docs/assets/
data.assets?.forEach((asset) => {
Expand Down
15 changes: 15 additions & 0 deletions site/examples/ecosystem/lottie/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,27 @@
},
"screenshot": "https://gw.alipayobjects.com/zos/raptor/1667977747890/A_NVmwSb89Y3kAAAAAAAAAAAAAARQnAQ.gif"
},
{
"filename": "radar.js",
"title": {
"zh": "雷达",
"en": "Radar"
},
"screenshot": "https://gw.alipayobjects.com/zos/raptor/1669793623610/radar.gif"
},
{
"filename": "ant.js",
"title": {
"zh": "蚂蚁形象",
"en": "Ant"
}
},
{
"filename": "spring.js",
"title": {
"zh": "弹簧",
"en": "Spring"
}
}
]
}
90 changes: 90 additions & 0 deletions site/examples/ecosystem/lottie/demo/radar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Canvas, CanvasEvent } from '@antv/g';
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
import { Renderer as CanvaskitRenderer } from '@antv/g-canvaskit';
import { loadAnimation } from '@antv/g-lottie-player';
import { Renderer as SVGRenderer } from '@antv/g-svg';
import { Renderer as WebGLRenderer } from '@antv/g-webgl';
import { Renderer as WebGPURenderer } from '@antv/g-webgpu';
import * as lil from 'lil-gui';
import Stats from 'stats.js';
import * as d3 from 'd3';

/**
* @see https://lottiefiles.github.io/lottie-docs/concepts/#transform
*/

// create a renderer
const canvasRenderer = new CanvasRenderer();
const svgRenderer = new SVGRenderer();
const webglRenderer = new WebGLRenderer();
const webgpuRenderer = new WebGPURenderer();
const canvaskitRenderer = new CanvaskitRenderer({
wasmDir: '/',
fonts: [
{
name: 'sans-serif',
url: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/file/A*064aSK2LUPEAAAAAAAAAAAAADmJ7AQ/NotoSansCJKsc-VF.ttf',
},
],
});

// create a canvas
const canvas = new Canvas({
container: 'container',
width: 600,
height: 500,
renderer: canvasRenderer,
});

canvas.addEventListener(CanvasEvent.READY, async () => {
const data = await d3.json('/lottie/radar.json');
const animation = loadAnimation(data, { loop: true });
const wrapper = animation.render(canvas);
});

// stats
const stats = new Stats();
stats.showPanel(0);
const $stats = stats.dom;
$stats.style.position = 'absolute';
$stats.style.left = '0px';
$stats.style.top = '0px';
const $wrapper = document.getElementById('container');
$wrapper.appendChild($stats);
canvas.addEventListener(CanvasEvent.AFTER_RENDER, () => {
if (stats) {
stats.update();
}
});

// GUI
const gui = new lil.GUI({ autoPlace: false });
$wrapper.appendChild(gui.domElement);
const rendererFolder = gui.addFolder('renderer');
const rendererConfig = {
renderer: 'canvas',
};
rendererFolder
.add(rendererConfig, 'renderer', [
'canvas',
'svg',
'webgl',
'webgpu',
'canvaskit',
])
.onChange((rendererName) => {
let renderer;
if (rendererName === 'canvas') {
renderer = canvasRenderer;
} else if (rendererName === 'svg') {
renderer = svgRenderer;
} else if (rendererName === 'webgl') {
renderer = webglRenderer;
} else if (rendererName === 'webgpu') {
renderer = webgpuRenderer;
} else if (rendererName === 'canvaskit') {
renderer = canvaskitRenderer;
}
canvas.setRenderer(renderer);
});
rendererFolder.open();
90 changes: 90 additions & 0 deletions site/examples/ecosystem/lottie/demo/spring.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Canvas, CanvasEvent } from '@antv/g';
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
import { Renderer as CanvaskitRenderer } from '@antv/g-canvaskit';
import { loadAnimation } from '@antv/g-lottie-player';
import { Renderer as SVGRenderer } from '@antv/g-svg';
import { Renderer as WebGLRenderer } from '@antv/g-webgl';
import { Renderer as WebGPURenderer } from '@antv/g-webgpu';
import * as lil from 'lil-gui';
import Stats from 'stats.js';
import * as d3 from 'd3';

/**
* @see https://lottiefiles.github.io/lottie-docs/concepts/#transform
*/

// create a renderer
const canvasRenderer = new CanvasRenderer();
const svgRenderer = new SVGRenderer();
const webglRenderer = new WebGLRenderer();
const webgpuRenderer = new WebGPURenderer();
const canvaskitRenderer = new CanvaskitRenderer({
wasmDir: '/',
fonts: [
{
name: 'sans-serif',
url: 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/file/A*064aSK2LUPEAAAAAAAAAAAAADmJ7AQ/NotoSansCJKsc-VF.ttf',
},
],
});

// create a canvas
const canvas = new Canvas({
container: 'container',
width: 600,
height: 500,
renderer: canvasRenderer,
});

canvas.addEventListener(CanvasEvent.READY, async () => {
const data = await d3.json('/lottie/spring.json');
const animation = loadAnimation(data, { loop: true });
const wrapper = animation.render(canvas);
});

// stats
const stats = new Stats();
stats.showPanel(0);
const $stats = stats.dom;
$stats.style.position = 'absolute';
$stats.style.left = '0px';
$stats.style.top = '0px';
const $wrapper = document.getElementById('container');
$wrapper.appendChild($stats);
canvas.addEventListener(CanvasEvent.AFTER_RENDER, () => {
if (stats) {
stats.update();
}
});

// GUI
const gui = new lil.GUI({ autoPlace: false });
$wrapper.appendChild(gui.domElement);
const rendererFolder = gui.addFolder('renderer');
const rendererConfig = {
renderer: 'canvas',
};
rendererFolder
.add(rendererConfig, 'renderer', [
'canvas',
'svg',
'webgl',
'webgpu',
'canvaskit',
])
.onChange((rendererName) => {
let renderer;
if (rendererName === 'canvas') {
renderer = canvasRenderer;
} else if (rendererName === 'svg') {
renderer = svgRenderer;
} else if (rendererName === 'webgl') {
renderer = webglRenderer;
} else if (rendererName === 'webgpu') {
renderer = webgpuRenderer;
} else if (rendererName === 'canvaskit') {
renderer = canvaskitRenderer;
}
canvas.setRenderer(renderer);
});
rendererFolder.open();

0 comments on commit ea3560f

Please sign in to comment.