react-native 类似购物车动画

react-native 类似购物车动画

今天我们来讲讲react-native如何实现类似点击商品出现一个抛物线到购物车的动画。
首先需要你需要react-native的Animated的用法([Animated](http://blog.csdn.net/sinat_17775997/article/details/54933752))。
  • 1
  • 2
  • 3

这里写图片描述

接下来我们就简单的Demo用代码来实现,点击+号出现一个抛物线飞到购物车的动画效果。

'use strict'

import React, { Component } from 'react'
import {
    Text,
    View,
    Image,
    StyleSheet,
    ScrollView,
    Dimensions,
    Animated,
    TouchableOpacity,
    findNodeHandle,
    UIManager,
    Alert,
    Easing
} from 'react-native'

import Icon from 'react-native-vector-icons/Ionicons'

let {width, height} = Dimensions.get('window')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

导入我们需要的包

export default class BuyCar extends Component{
    constructor(props){
        super(props)
        this.state = {
            animateBtnX: 0,
            animateBtnY: -999,
            addBtnY: -999,
            addBtnX:0,
            runAnim: new Animated.Value(0),
            endX: 26,// 购物车的位置 在距屏幕的左侧26像素
            endY: height-44, // 购物车的位置 在距屏幕的底部44像素
            curvature: .003, // 动画抛高系数,值越大抛的越高
            duration: 800, // 动画运动时间
        }
    }

    // 获取点击坐标XY
    getScreenXY(i,item){
        const self = this;
        const handle = findNodeHandle(this.refs[i]);
        UIManager.measure(handle, (x,y,width,height,pageX,pageY) => {
            console.log(x,y,width,height,pageX,pageY)
            let data=item,
            let pos= [pageX, pageY, self.state.endX, self.state.endY],
            self.setState({
                addBtnY: pageY,
                addBtnX: pageX
            })
            self.run(pos,data)
        })
    }
    //运行动画
    run(position = [],data = {}){
        if(position.length != 4){
            return
        }
        this.state.runAnim.setValue(0)
        const { inputRange, outputX, outputY } = this.getPaths(position)
        // console.log(inputRange, outputX, outputY)
        this.setState({
            animateBtnX: this.state.runAnim.interpolate({
                inputRange:inputRange, outputRange: outputX
            }),
            animateBtnY: this.state.runAnim.interpolate({
                inputRange:inputRange, outputRange: outputY
            })
        })
        // console.log(this.state.animateBtnX,this.state.animateBtnY)
        Animated.timing(this.state.runAnim, {
            toValue: inputRange.length,
            duration: this.state.duration,
            easing: Easing.linear // 缓动函数
        }).start(()=>{
            this.state.runAnim.setValue(0)
            this.setState({
                addBtnY: -999,
                addBtnX: 0
            })
        })
    }
    // 获得路径
    getPaths(position){
        const [ startX, startY, endX, endY ] = position
        const { curvature } = this.state, speed = 500//166.67
        let diffX = endX - startX,
            diffY = endY - startY;
        let b = ( diffY - curvature * diffX * diffX ) / diffX,
            start_x = 0,
            rate = diffX > 0? 1: -1,
            inputRange = [], outputX = [], outputY = [];
        let step = () => {
            let tangent = 2 * curvature * start_x + b;
            start_x = start_x + rate * Math.sqrt(speed / (tangent * tangent + 1));
            if ((rate == 1 && start_x > diffX) || (rate == -1 && start_x < diffX)) {
                start_x = diffX;
            }
            let x = start_x, y = curvature * x * x + b * x;
            inputRange.push(outputX.length)
            outputX.push(x)
            outputY.push(y)
            if (start_x !== diffX) {
                step()
            }
        }
        step()
        return { inputRange, outputX, outputY }
    }

    render(){
        return(
            <View style={styles.fullScreen}>
                <ScrollView style={styles.scrollView}>
                    {
                        ['美国队长','绿箭侠','超人','蝙蝠侠','蚁人','绿巨人','猫女','钢铁侠','雷神托尔','黑寡妇','鹰眼侠','葫芦娃','孙悟空','牛魔王','哪吒','唐僧'].map((item, i) => {
                            return(
                                    <View style={styles.addBtn} key={i}>
                                        <TouchableOpacity  ref={i} onPress={this.getScreenXY.bind(this,i,item)}>
                                        <Icon name={"ios-add-circle"} size={26} color={"#3190e8"} />
                                        </TouchableOpacity>
                                        <Text style={{fontSize: 14, color: '#333',paddingHorizontal:10}}>{item}</Text>
                                    </View>
                            )
                        })
                    }
                </ScrollView>
                <Animated.View style={[styles.tmpBtn, {
                    top:this.state.addBtnY,
                    left: this.state.addBtnX,
                    transform: [
                        { translateX: this.state.animateBtnX },
                        { translateY: this.state.animateBtnY },
                    ]
                }]}>
                    <View style={{width:20, height:20,backgroundColor:"red", borderRadius: 20}}></View>
                </Animated.View>
                <View style={{position:'absolute',bottom:0, left:0,width:width,height:60,flexDirection:'row'}}>
                    <View style={{flex:2,backgroundColor:'#3190e8'}}></View>
                    <View style={{flex:8,backgroundColor:'#000000'}}></View>
                </View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    fullScreen: {
        flex:1,
        alignItems: "center",
        justifyContent: "center",
    },
    addBtn:{
        backgroundColor: "pink",
        alignItems: "center",
        justifyContent: "center",
        flexDirection: 'row',
        paddingVertical: 10,
    },
    scrollView:{
        marginBottom:60,
    },
    tmpBtn: {
        position: "absolute",
        backgroundColor:'red',
        width:20,
        height:20,
        borderRadius:20
    }
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36091581/article/details/79204282

猜你喜欢

转载自blog.csdn.net/sinat_17775997/article/details/81073122