为了账号安全,请及时绑定邮箱和手机立即绑定

React 使用 JS 动画

标签:
JavaScript

上一篇博客讲了React官方提供的TransitionGroup动画库,它实现的原理是典型的CC3方式,现在再来了解一下如何使用脚本的方式来实现动画。要使用脚本的方式实现动,我们可以采用react-motion这个动画库,它是一个很优秀的动画库,并且采用的是脚本的方式来实现动画。(motion是运动的意思)

react-motion :  https://github.com/chenglou/react-motion

1.安装react-motion动画库

yarn add react-motion//ro  npm install react-motion123

2.计数器案例

该案例实现由数字 0 加到 1

这里写图片描述

1.从react-motion库中导入 spring 和 Motion

spring : 指定如何为目标值设置动画,例如,spring(10, {stiffness: 120, damping: 17})表示“动            画到数值10,弹簧刚度为120,阻尼为17”

Motion :  它是一个专门提供动画数据的组件,它接收一个函数作为子组件,  例如:

< motion >
   { value  => (   ) } 
</ Motion >123

2.Motion组件属性:

defaultStyle : 设置动画开始前默认数值

style : 设置动画要到数值

import React, {Component} from 'react';
import {spring ,Motion} from 'react-motion';

export default class Main extends Component {
    render() {        return (
            <div style={styles.content}>
                {/*由0 过渡到 1 ; stiffness是阻尼*/}
                <Motion defaultStyle={{x: 0}} style={{x: spring(1,{stiffness: 20})}}>
                    {
                        value =>
                            <div>
                                {value.x}
                            </div>
                    }
                </Motion>
            </div>
        )
    }
}/*样式*/const styles = {
    content: {
        width: '400px',
        height: '500px',
        backgroundColor: 'skyblue',
        margin: '0 auto',
    },
}123456789101112131415161718192021222324252627282930

执行的效果:

这里写图片描述

2.改变透明度和宽的动画案例

通过上面的案例可以知道 Motion 组是专门提供动画数据的 ,其实它并没有参与界面的绘制,界面的绘制过程是通过子组件来完成的。下面我们来做一个改变透明度和宽的动画案例

1.从react-motion库中导入 spring 和 Motion

2.value.x的值是由0过渡到1的, 可以通过Motion提供的这个动画数据类修改div的 透明度和宽度

3.${value.x} 两边添加了反引号,这个是es6中的字符串模板语法。${} 可以理解为插值器

import React, {Component} from 'react';

import {spring ,Motion} from 'react-motion';

export default class Main extends Component {

    render() {        return (
            <div style={styles.content}>
                {/*由0 过渡到 1 ; stiffness是阻尼*/}
                ......

                {/*改变div的宽度和透明度*/}
                <Motion defaultStyle={{x: 0}} style={{x: spring(1,{stiffness: 20})}}>
                    {
                        value =>

                            <div style={ Object.assign({},styles.divStyle,{
                                opacity:`${value.x}`,
                                width:`${50+value.x*100}px`
                            })}>
                                默认
                            </div>
                    }
                </Motion>

            </div>
        )
    }


}/*样式*/const styles = {
    content: {
       ....
    },
    divStyle: {
        width: '50px',
        height: '50px',
        backgroundColor: 'green',
        margin: '3px 0',
        color:'white'
    },
}123456789101112131415161718192021222324252627282930313233343536373839404142434445

刷新界面执行到0.2的效果:

这里写图片描述

执行结束后的结果:

这里写图片描述

3.TransitionMotion执行装载和卸载动画案例

之前学的TransitionGroup动画库提供了执行组件的装载和御载的动画。其实react-motion也提供了这个功能,要使用这个功能就要用到一个新的API : TransitionMotion 组件,该组件可以帮助您执行组件的装载和卸载动画。

1.从react-motion库中导入 TransitionMotion, spring 和 presets

TransitionMotion 是执行组件的装载和卸载动画

spring  : 指定如何为目标值设置动画

presets : 预设设刚度和阻尼的值

2.添加组件时:状态由willEnter()中定义的状态过渡到styles中定义的状态

willEnter(){
        return {width: 0, height: 0};}
// 由willEnter()中width: 0, height: 0状态过渡到下面styles中width:200, height: 50状态
// spring() 函数为目标值设置动画
// presets.wobbly 等价于 {stiffness: 180, damping: 12}
 styles={this.state.items.map(item => ({
                        key: item.key,
                        style: {width: spring(item.w,presets.wobbly), height: spring(50,presets.wobbly)},
                    }))}12345678910

3.删除组件时:状态由styles中定义的状态过渡到willLeave中定义的状态

 styles={this.state.items.map(item => ({
                        key: item.key,
                        style: {width: spring(item.w,presets.wobbly), height: spring(50,presets.wobbly)},
                    }))}
// 由styles中width:200, height: 50状态过渡到下面willEnter()中width: 0, height: 0 状态
// presets.wobbly 等价于 {stiffness: 180, damping: 12}
//下面的 spring(0,presets.wobbly) 设置目标值动画                
willLeave() {
        return {width: spring(0,presets.wobbly), height: spring(0,presets.wobbly)};}12345678910

案例完整的代码:

import React, {Component} from 'react';
import {TransitionMotion,spring , presets} from 'react-motion';

export default class Main extends Component {

    constructor(props) {        super(props);        /*定义一个数组:目标状态*/
        this.state={
            items: [{key: 'a', w: 200},{key: 'b', w: 200}],
        }
    }    /*装载组件的状态( 进入/添加组件 )*/
    willEnter(){        return {width: 0, height: 0};
    }    /*御载组件的状态( 离开/删除组件 )*/
    willLeave() {        return {width: spring(0,presets.wobbly), height: spring(0,presets.wobbly)};
    }

    render() {        return (
            <div style={styles.content}>

                <TransitionMotion
                    willEnter={this.willEnter}
                    willLeave={this.willLeave}
                    styles={this.state.items.map(item => ({
                        key: item.key,
                        style: {width: spring(item.w,presets.wobbly), height: spring(50,presets.wobbly)},
                    }))}>

                    {interpolatedStyles =>
                        <div>
                            {interpolatedStyles.map(config => {                                return <div key={config.key} style={{...config.style, border: '1px solid'}} >
                                    {config.key} : {config.style.height}
                                </div>
                            })}
                        </div>
                    }
                </TransitionMotion>
                <button onClick={()=>this.startAnimation(0)}>Add C</button>
                <button onClick={()=>this.startAnimation(1)}>remove C</button>

            </div>
        )
    }

    startAnimation(index){        // add
        if(index==0){            this.setState({
                items: [{key: 'a', w: 200},{key: 'b', w: 200},{key: 'c', w: 200}],
            })        // remove
        }else{            this.setState({
                items: [{key: 'a', w: 200},{key: 'b', w: 200}],
            })
        }

    }

}/*样式*/const styles = {
    content: {
        width: '400px',
        height: '500px',
        backgroundColor: 'skyblue',
        margin: '0 auto',
    },
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677

刷新浏览器默认的状态:

这里写图片描述

点击 Add C 后,添加一个div, 宽和高在慢慢的变大

这里写图片描述

原文出处

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消