天天看点

rn自定义精美动画按钮组件

效果

rn自定义精美动画按钮组件
rn自定义精美动画按钮组件

所谓的自定义指的是自定义按钮的大小,文字内容,背景颜色,两个小球的颜色小球的大小根据按钮的宽高变化,小球运动的终点是一个随机数的一个区间

代码 用了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'
/>
           

继续阅读