效果
所谓的自定义指的是自定义按钮的大小,文字内容,背景颜色,两个小球的颜色小球的大小根据按钮的宽高变化,小球运动的终点是一个随机数的一个区间
代码 用了styled-component (尝试在函数式组件里写动画,果然很勉强)
import React, { useState, useEffect } from 'react'
import { Animated, TouchableNativeFeedback } from 'react-native'
import styled from 'styled-components'
import { Title } from './index'
const AnimatedButton = ({ title, width, height, bgc, bigColor, smColor, onPress, size }) => {
const [BigRoundX, setBigRoundX] = useState(new Animated.Value(0))
const [BigRoundY, setBigRoundY] = useState(new Animated.Value(0))
const [SmRoundX, setSmRoundX] = useState(new Animated.Value(-(100 + Math.random() * 200)))
const [SmRoundY, setSmRoundY] = useState(new Animated.Value(-(Math.random() * 150)))
function add () {
const randomX = -(250 + (Math.random() * 100))
const randomY = -(100 + (Math.random() * 100))
const randomSmX = -(Math.random() * 50)
const randomSmY = -(Math.random() * 50)
Animated.timing(BigRoundX, { toValue: randomX, duration: 20000, useNativeDriver: false }).start()
Animated.timing(BigRoundY, { toValue: randomY, duration: 20000, useNativeDriver: false }).start()
Animated.timing(SmRoundX, { toValue: randomSmX, duration: 20000, useNativeDriver: false }).start()
Animated.timing(SmRoundY, { toValue: randomSmY, duration: 20000, useNativeDriver: false }).start(() => reduce())
}
function reduce () {
const randomX = (Math.random() * 50)
const randomY = (Math.random() * 50)
const randomSmX = -(200 + (Math.random() * 100))
const randomSmY = -(100 + (Math.random() * 100))
Animated.timing(BigRoundX, { toValue: randomX, duration: 20000, useNativeDriver: false }).start()
Animated.timing(BigRoundY, { toValue: randomY, duration: 20000, useNativeDriver: false }).start()
Animated.timing(SmRoundX, { toValue: randomSmX, duration: 20000, useNativeDriver: false }).start()
Animated.timing(SmRoundY, { toValue: randomSmY, duration: 20000, useNativeDriver: false }).start(() => add())
}
useEffect(() => {
add()
})
return (
<TouchableNativeFeedback onPress={() => {
if (!onPress) return
onPress()
}}>
<Container bgc={bgc} width={width} height={height}>
<Title shadow size={size || '40px'} style={{ elevation: 50 }}>{title}</Title>
<AnimatedRound
bgc={bigColor}
style={{
elevation: 10,
transform: [
{ translateX: BigRoundX },
{ translateY: BigRoundY }
]
}} />
<AnimatedRound
bgc={smColor || '#a5f'}
style={{
elevation: 40,
transform: [
{ translateX: SmRoundX },
{ translateY: SmRoundY }
]
}}
width='20%' height='40%' />
</Container>
</TouchableNativeFeedback>
)
}
export default AnimatedButton
const Round = styled.View`
position: absolute;
width: ${props => props.width || '60%'};
height: ${props => props.height || '120%'};
background-color: ${props => props.bgc || '#f77'};
border-radius: 1000px;
right: ${props => props.right || '-30%'};
bottom: ${props => props.bottom || '-50%'};
z-index: -1;
`
const AnimatedRound = Animated.createAnimatedComponent(Round)
const Container = styled.View`
width: ${props => props.width || '300px'};
height: ${props => props.height || '150px'};
background-color: ${props => props.bgc || '#7f7'};
border-radius: 10px;
justify-content: center;
align-items: center;
overflow: hidden;
`
Title样式
export const Title = styled.Text`
color: ${props => props.color || '#fffae5'};
font-weight: bold;
text-align: center;
font-size: ${props => props.size || '25px'};
text-shadow: ${props => props.shadow ? '0 0 2px #00f' : '0 0 0 #000'};
text-transform: ${props => props.textT || 'uppercase'};
`
使用
<AnimatedButton title='default' />
<AnimatedButton
title='Custom Title'
width='200px'
height='100px'
bgc='#fffaaa'
bigColor='#afa'
smColor='#aaa'
/>