Animate 动画
如果项目中使用的是 0.x 版本的基础组件(@icedesign/base, @ali/ice, @alife/next),请在左侧导航顶部切换组件版本。
安装方法
- 在命令行中执行以下命令
npm install @alifd/next@latest -S
开发指南
何时使用
需要自定义动效
API
Animate
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
animation | 动画 className | String/Object | - |
animationAppear | 子元素第一次挂载时是否执行动画 | Boolean | true |
component | 包裹子元素的标签 | any | 'div' |
singleMode | 是否只有单个子元素,如果有多个子元素,请设置为 false | Boolean | true |
children | 子元素 | ReactElement/Array<ReactElement> | - |
beforeAppear | 执行第一次挂载动画前触发的回调函数签名:Function() => void | Function | () => {} |
onAppear | 执行第一次挂载动画,添加 xxx-appear-active 类名后触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
afterAppear | 执行完第一次挂载动画后触发的函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
beforeEnter | 执行进场动画前触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
onEnter | 执行进场动画,添加 xxx-enter-active 类名后触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
afterEnter | 执行完进场动画后触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
beforeLeave | 执行离场动画前触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
onLeave | 执行离场动画,添加 xxx-leave-active 类名后触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
afterLeave | 执行完离场动画后触发的回调函数签名:Function(node: HTMLElement) => void参数:node: {HTMLElement} 执行动画的 dom 元素 | Function | () => {} |
Animation List
In | Out |
---|---|
fadeIn | fadeOut |
fadeInDown | fadeOutDown |
fadeInLeft | fadeOutLeft |
fadeInRight | fadeOutRight |
fadeInUp | fadeOutUp |
zoomIn | zoomOut |
expandInDown | expandOutUp |
expandInUp | expandOutDown |
pulse |
代码示例
展示单个子元素的进场离场动画。
查看源码在线预览
import { Animate } from '@alifd/next';
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = { visible: true };
this.handleToggle = this.handleToggle.bind(this);
}
handleToggle() {
this.setState({
visible: !this.state.visible
});
}
render() {
return (
<div>
<button onClick={this.handleToggle}>Toggle visible</button>
<Animate animation={{
enter: 'my-zoom-in',
leave: 'my-zoom-out'
}}>
{this.state.visible ?
<div className="basic-demo">Next Animate</div> :
null}
</Animate>
</div>
);
}
}
ReactDOM.render(<Demo />, mountNode);
.basic-demo {
font-size: 96px;
text-align: center;
}
.my-zoom-in {
opacity: 0;
}
.my-zoom-in-active {
animation: my-zoom-in 500ms linear;
}
.my-zoom-out {
opacity: 1;
}
.my-zoom-out-active {
animation: my-zoom-out 500ms linear;
}
@keyframes my-zoom-in {
from {
opacity: 0;
transform: scale3d(.3, .3, .3);
}
50% {
opacity: 1;
}
to {
opacity: 1;
}
}
@keyframes my-zoom-out {
from {
opacity: 1;
}
50% {
opacity: 0;
transform: scale3d(.3, .3, .3);
}
to {
opacity: 0;
}
}
展示多个子元素的进场离场动画。
查看源码在线预览
import { Animate } from '@alifd/next';
class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = { items: ['hello', 'world', 'click', 'me'] };
}
handleAdd() {
this.setState({
items: [
...this.state.items,
// eslint-disable-next-line
prompt('Enter some text')
]
});
}
handleRemove(i) {
const newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({ items: newItems });
}
render() {
return (
<div className="totolist-container">
<Animate animationAppear animation="fade" className="todo-list" singleMode={false}
beforeAppear={() => console.log('before appear')}
onAppear={() => console.log('appear')}
afterAppear={() => console.log('after appear')}
beforeEnter={() => console.log('before enter')}
onEnter={() => console.log('enter')}
afterEnter={() => console.log('after enter')}
beforeLeave={() => console.log('before leave')}
onLeave={() => console.log('leave')}
afterLeave={() => console.log('after leave')}>
{this.state.items.map((item, i) => (
<div key={item}>
{item}
<button onClick={() => this.handleRemove(i)}>
×
</button>
</div>
))}
</Animate>
<button onClick={() => this.handleAdd()}>Add Item</button>
</div>
);
}
}
ReactDOM.render(<TodoList />, mountNode);
.fade-appear {
opacity: 0.01;
}
.fade-appear.fade-appear-active {
opacity: 1;
transition: opacity 1000ms ease-in;
}
.fade-enter {
opacity: 0.01;
}
.fade-enter.fade-enter-active {
opacity: 1;
transition: opacity 1000ms ease-in;
}
.fade-leave {
opacity: 1;
}
.fade-leave.fade-leave-active {
opacity: 0.01;
transition: opacity 800ms ease-in;
}
.totolist-container {
padding: 20px;
border: 1px solid #ccc;
width: 200px;
border-radius: 4px;
}
.todo-list > * {
margin: 5px 0;
padding: 5px 0;
border-bottom: 1px solid #ccc;
}
.totolist-container > button {
margin-top: 20px;
}
展示单个子元素的展开收起动画。
查看源码在线预览
import { Animate } from '@alifd/next';
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = { expand: true };
['beforeEnter', 'onEnter', 'afterEnter', 'beforeLeave', 'onLeave', 'afterLeave', 'handleToggle'].forEach(method => {
this[method] = this[method].bind(this);
});
}
handleToggle() {
this.setState({
expand: !this.state.expand
});
}
beforeEnter(node) {
this.height = node.offsetHeight;
node.style.height = '0px';
}
onEnter(node) {
node.style.height = `${this.height}px`;
}
afterEnter(node) {
this.height = null;
node.style.height = null;
}
beforeLeave(node) {
node.style.height = `${this.height}px`;
}
onLeave(node) {
node.style.height = '0px';
}
afterLeave(node) {
node.style.height = null;
}
render() {
return (
<div>
<button onClick={this.handleToggle}>Toggle expand</button>
<Animate animation="expand"
beforeEnter={this.beforeEnter}
onEnter={this.onEnter}
afterEnter={this.afterEnter}
beforeLeave={this.beforeLeave}
onLeave={this.onLeave}
afterLeave={this.afterLeave}>
{this.state.expand ?
<div className="notice"></div> :
null}
</Animate>
</div>
);
}
}
ReactDOM.render(<Demo />, mountNode);
.expand-enter {
overflow: hidden;
}
.expand-enter-active {
transition: height 0.3s ease-out;
}
.expand-leave {
overflow: hidden;
}
.expand-leave-active {
transition: height 0.3s ease-out;
}
.notice {
width: 200px;
height: 100px;
margin-top: 20px;
border: 1px solid #ccc;
}