Skip to content

Commit

Permalink
feat(animation): 增加动画文档和 demo & 多图层图表支持分view动画 (#2291)
Browse files Browse the repository at this point in the history
* docs(animation): 增加动画文档

* feat(multi-view): 多图层图表支持不同view配置不同的动画效果

* docs(animation): 添加动画文档 & 增加一个缓动效果的 demo

* docs(demo): 修改 demo 的 meta 信息

* test: 增加单测

* docs: 优化 demo

* docs: 增加折线图和柱状图的动画 demo

* docs(demo): 增加饼图动画 demo

* docs(demo): demo 中增加无动画的选项

* docs: api 文档增加跳转demo的链接

* fix: 修改 ci 问题

* fix: 移除暂时使用不到的类型定义
  • Loading branch information
visiky authored Feb 1, 2021
1 parent 97c520d commit 9e62cb9
Show file tree
Hide file tree
Showing 14 changed files with 548 additions and 5 deletions.
39 changes: 38 additions & 1 deletion __tests__/unit/plots/multi-view/index-spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Lab } from '../../../../src';
import { Lab, MultiView } from '../../../../src';
import { createDiv } from '../../../utils/dom';
import { partySupport } from '../../../data/party-support';

Expand Down Expand Up @@ -147,4 +147,41 @@ describe('multi-view', () => {
// `enable: false` 移除交互
expect(line.chart.views[1].interactions['tooltip']).not.toBeDefined();
});

it('animation for each view', () => {
const data = new Array(30).fill(1).map((d, idx) => ({ x: `${idx}`, y: idx + Math.random() * 10 }));
const plot = new MultiView(createDiv(), {
animation: false,
views: [
{
data,
region: { start: { x: 0, y: 0 }, end: { x: 0.5, y: 1 } },
geometries: [{ type: 'line', xField: 'x', yField: 'y', mapping: {} }],
},
{
data,
region: { start: { x: 0.5, y: 0 }, end: { x: 1, y: 1 } },
geometries: [{ type: 'line', xField: 'x', yField: 'y', mapping: {} }],
},
],
});
plot.render();
// @ts-ignore
expect(plot.chart.options.animate).toBe(false);

plot.update({ animation: { appear: { animation: 'fade-in' } } });
// @ts-ignore
expect(plot.chart.options.animate).toBe(true);
// @ts-ignore chart 上的设置不可生效, todo 是否要作用到每个 view 上
expect(plot.chart.views[0].geometries[0].animateOption).not.toBeDefined();

const views = plot.options.views;
// @ts-ignore
views[0].animation = { appear: { animation: 'fade-in' } };
plot.update({ animation: false, views });
// @ts-ignore
expect(plot.chart.views[0].options.animate).toBe(true);
// @ts-ignore
expect(plot.chart.views[0].geometries[0].animateOption.appear.animation).toBe('fade-in');
});
});
38 changes: 38 additions & 0 deletions docs/api/options/animation.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Animation
order: 2
---


#### Usage

<b>图形动画配置有两种方式:</b>

第一种,传入 `false` 设置关闭动画。

```ts
animation: false; // close animation
```

第二种,传入 _AnimateOption_ 对进行动画参数配置。

```ts
animation: {
// Configuration of the first animation
appear: {
animation: 'wave-in', // Effects of the first animation
duration: 5000, // Duration of the first animation
},
}
```

#### Configuration(_AnimateOption_

`markdown:docs/common/animate-option.zh.md`

#### Easing Effects

Easing method used to control apparent motion in animation. Varied easing effects can be found at [d3-ease](https://github.com/d3/d3-ease)

<playground path="dynamic-plots/animation/demo/easing-effects.ts" rid="easing-effect"></playground>

39 changes: 39 additions & 0 deletions docs/api/options/animation.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: 图形动画
order: 2
---

#### 使用方式

<b>图形动画配置有两种方式:</b>

第一种,传入 `false` 设置关闭动画。

```ts
animation: false; // 关闭动画
```

第二种,传入 _AnimateOption_ 对进行动画参数配置。


```ts
animation: {
// 配置图表第一次加载时的入场动画
appear: {
animation: 'wave-in', // 动画效果
duration: 5000, // 动画执行时间
},
}
```

#### 配置项(_AnimateOption_

`markdown:docs/common/animate-option.zh.md`

#### 缓动效果 (_Easing Effects_)

`easing` 用来控制动画中的缓动效果,更多的缓动效果可以参见 [d3-ease](https://github.com/d3/d3-ease)

<playground path="dynamic-plots/animation/demo/easing-effects.ts" rid="easing-effect"></playground>


6 changes: 5 additions & 1 deletion docs/common/animate-option.en.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class='custom-api-docs'>

_ComponentAnimateOption_ is configured for each component animation type. Where 'easing' passes in the name of the animation function, the built-in default animation function is shown in the table below, and you can also customize the animation function through 'registerAnimation'.
_ComponentAnimateOption_ is configured for each component animation type.

```ts
interface ComponentAnimateOption {
Expand All @@ -17,6 +17,10 @@ interface ComponentAnimateCfg {
}
```

Where 'animation' passes in the name of the animation function, the built-in default animation function is shown in the table below, and you can also customize the animation function through 'registerAnimation'.

**Effects of animation**, go to see [Examples](/en/examples/dynamic-plots/animation) for more information

| Animation | Effect | Description |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| 'fade-in' | ![fade-in.gif](https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*LTRRRL8JwfQAAAAAAAAAAABkARQnAQ) | 渐现动画。 |
Expand Down
9 changes: 7 additions & 2 deletions docs/common/animate-option.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class='custom-api-docs'>

_ComponentAnimateOption_ 为组件各个动画类型配置。其中 `easing` 传入动画函数名称,内置默认动画函数如下表,同时也可以通过 `registerAnimation` 自定义动画函数。
_ComponentAnimateOption_ 为组件各个动画类型配置。

```ts
interface ComponentAnimateOption {
Expand All @@ -11,13 +11,18 @@ interface ComponentAnimateOption {
}

interface ComponentAnimateCfg {
animation?: string; // 动画效果,内置的动画效果见下表,也可以通过自定义动画的方式实现自定义效果
duration?: number; // 动画执行时间
easing?: string; // 动画缓动函数
delay?: number; // 动画延迟时间
}
```

| animation | 效果 | 说明 |
其中 `animation` 传入动画函数名称,内置默认动画函数如下表,同时也可以通过 `registerAnimation` 自定义动画函数。

**动画效果**,前往[图表示例](/zh/examples/dynamic-plots/animation)查看效果

| animation | 效果 | 说明 |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| 'fade-in' | ![fade-in.gif](https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*LTRRRL8JwfQAAAAAAAAAAABkARQnAQ) | 渐现动画。 |
| 'fade-out' | ![fade-out.gif](https://gw.alipayobjects.com/mdn/rms_f5c722/afts/img/A*s4Y4S5JJ6WEAAAAAAAAAAABkARQnAQ) | 渐隐动画。 |
Expand Down
85 changes: 85 additions & 0 deletions examples/dynamic-plots/animation/demo/animation-column.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Select, Input } from 'antd';
import { Column } from '@antv/g2plot';
import insertCss from 'insert-css';

class ColumnPlot extends React.Component {
chartNodeRef = React.createRef();
chartRef = React.createRef();

componentDidMount() {
// Step 1: 声明数据源
// G2Plot 对数据源格式的要求,仅仅是 JSON 数组,数组的每个元素是一个标准 JSON 对象。
/** Generater a data array of 20 items */
const data = new Array(20).fill(1).map((d, idx) => ({ x: `${idx}`, y: idx + Math.random() * 20 }));
// Step 2: 创建图表
const chartDom = this.chartNodeRef.current;
const column = new Column(chartDom, {
data,
xField: 'x',
yField: 'y',
seriesField: 'x',
legend: false,
});

// Step 3: 渲染图表
column.render();
this.chartRef.current = column;
}

handleAnimationChange = (v) => {
const column = this.chartRef.current;
if (column) {
column.update({ animation: v === '无' ? false : { appear: { animation: v } } });
}
};

handleDurationChange = (e) => {
const v = e.target.value;
const column = this.chartRef.current;
if (column) {
column.update({ animation: { appear: { duration: v } } });
}
};

render() {
return (
<section>
<div>
<span className="select-label">切换动画</span>
<Select aria-label="select" defaultValue="scale-in-y" onChange={this.handleAnimationChange} size="small">
{/* 'grow-in-x', 'grow-in-y' 不可用*/}
{['scale-in-x', 'scale-in-y', 'zoom-in', 'zoom-out', 'fade-in', '无'].map((opt) => {
return <Select.Option value={opt}>{opt}</Select.Option>;
})}
</Select>
<span className="select-label">动画持续时间</span>
<Input aria-label="input" className="custom-input" placeholder="500ms" size="small" onChange={this.handleDurationChange} />
</div>
<div className={'chart-wrapper'} ref={this.chartNodeRef} />
</section>
);
}
}

// 我们用 insert-css 演示引入自定义样式
// 推荐将样式添加到自己的样式文件中
// 若拷贝官方代码,别忘了 npm install insert-css
insertCss(`
.select-label {
margin-right: 8px;
}
.select-label:not(:first-of-type) {
margin-left: 8px;
}
.custom-input {
display: incolumn-block;
width: 200px !important;
}
.chart-wrapper {
margin-top: 12px;
}
`);

ReactDOM.render(<ColumnPlot />, document.getElementById('container'));
82 changes: 82 additions & 0 deletions examples/dynamic-plots/animation/demo/animation-line.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Select, Input } from 'antd';
import { Line } from '@antv/g2plot';
import insertCss from 'insert-css';

class LinePlot extends React.Component {
chartNodeRef = React.createRef();
chartRef = React.createRef();

componentDidMount() {
// Step 1: 声明数据源
// G2Plot 对数据源格式的要求,仅仅是 JSON 数组,数组的每个元素是一个标准 JSON 对象。
/** Generater a data array of 50 items */
const data = new Array(50).fill(1).map((d, idx) => ({ x: `${idx}`, y: idx + Math.random() * 10 }));
// Step 2: 创建图表
const chartDom = this.chartNodeRef.current;
const line = new Line(chartDom, {
data,
xField: 'x',
yField: 'y',
});

// Step 3: 渲染图表
line.render();
this.chartRef.current = line;
}

handleAnimationChange = (v) => {
const line = this.chartRef.current;
if (line) {
line.update({ animation: v === '无' ? false : { appear: { animation: v } } });
}
};

handleDurationChange = (e) => {
const v = e.target.value;
const line = this.chartRef.current;
if (line) {
line.update({ animation: { appear: { duration: v } } });
}
};

render() {
return (
<section>
<div>
<span className="select-label">切换动画</span>
<Select aria-label="select" defaultValue="wave-in" onChange={this.handleAnimationChange} size="small">
{['wave-in', 'zoom-in', 'fade-in', '无'].map((opt) => {
return <Select.Option value={opt}>{opt}</Select.Option>;
})}
</Select>
<span className="select-label">动画持续时间</span>
<Input aria-label="input" className="custom-input" placeholder="500ms" size="small" onChange={this.handleDurationChange} />
</div>
<div className={'chart-wrapper'} ref={this.chartNodeRef} />
</section>
);
}
}

// 我们用 insert-css 演示引入自定义样式
// 推荐将样式添加到自己的样式文件中
// 若拷贝官方代码,别忘了 npm install insert-css
insertCss(`
.select-label {
margin-right: 8px;
}
.select-label:not(:first-of-type) {
margin-left: 8px;
}
.custom-input {
display: inline-block;
width: 200px !important;
}
.chart-wrapper {
margin-top: 12px;
}
`);

ReactDOM.render(<LinePlot />, document.getElementById('container'));
Loading

0 comments on commit 9e62cb9

Please sign in to comment.