React Native 组件分享(TipAb)
2022-12-13 本文已影响0人
G_console
分享一个自定义组件:可定时隐藏,可带循环动画的定位图片。
import {
ViewStyle,
StyleProp,
ImageURISource,
Animated,
} from 'react-native'
import Base from '@/components/Base';
import { Image } from '@/components';
interface Props {
source: ImageURISource
size: number
style?: StyleProp<ViewStyle>
duration?: number
freeze?: boolean //不能隐藏
onClick?: () => void
animation?: {
duration?: number
animatStyle: (e:any) => ViewStyle
}
}
interface State {
visible: boolean
}
/**
* **absolute图片**
* @param {number} duration 定时隐藏
* @param {boolean} freeze 不能隐藏
* @param {any} animation 循环动画
*
* ** animation Example: **
*
\\```animation={{
duration: 5000,
animatStyle: animat => {
return {
transform: [{scale: animat? animat.interpolate({
inputRange: [0, 1],
outputRange: [0.3, 1]
}): 1}],
opacity: animat,
bottom: animat?.interpolate({
inputRange: [0, 1],
outputRange: ['100%', '150%']
})
}
}
}}
\\```
*
* **/
export default class TipAb extends Base<Props, State> {
public state: State = {
visible: true
};
private animateVal: any;
public didMount() {
const { duration, freeze, animation } = this.props
let time = duration? duration: 5000
let that = this
if(!freeze) {
setTimeout(() => {
this.animating = false
that.setState({
visible: false
})
},time)
}
if(animation) {
this.animateVal = new Animated.Value(0);
setTimeout(() => {
this.animating = true
this.startAnimate()
}, 500)
}
}
public willUnmount() {
this.animating = false
}
private animating:boolean = true
private startAnimate = () => {
const { animation } = this.props
Animated.timing(this.animateVal, {
toValue: 1,
duration: animation?.duration || 3000,
useNativeDriver: false
}).start(({ finished }) => {
Animated.timing(this.animateVal, {
toValue: 0,
duration: animation?.duration || 3000,
useNativeDriver: false
}).start(({ finished }) => {
if(this.animating) {
this.startAnimate()
}
});
});
}
public render() {
const { visible } = this.state
const { source, size, style, animation } = this.props
return visible? (
<Animated.View style={[{
position: 'absolute',
zIndex: 9
}, style, animation?.animatStyle(this.animateVal) || {}]}>
<Image
onClick={this.handleClick}
source={source}
width={size}
/>
</Animated.View>
): null;
}
private handleClick = () => {
const { onClick, freeze } = this.props
if(!freeze){
this.animating = false
this.setState({
visible: false
})
}
if(onClick){
onClick()
}
}
}
使用:
import TipAb from "@/components/TipAb";
//...
render() {
return (
<TipAb source={this.assets.arrDownImage} size={25}
freeze={true}
style={{
bottom: '100%',
left: 0,
}}
animation={{
duration: 1500,
animatStyle: animat => {
return {
transform: [{translateY: animat? animat.interpolate({
inputRange: [0, 1],
outputRange: [0, -10]
}): 0}],
}
}
}}
/>
)
}