最近在做ReactNative项目,我们的页面有很多图片,发现图片加载效果很卡顿。于是研究了一下RN下图片渐进加载。
原理
首先给图片一个固定宽高的容器,容器中有两个透明度为0的 Image 元素, 其中一个加载缩略图,一个为原图,监听图片加载,调整透明度,给过渡动画。
依赖
react-native-fast-image 用于缓存图片
react-spring/native 用于实现动画效果
对比图
优化前
优化后
核心代码
import React, { FC } from 'react'
import { View, StyleSheet, ImageStyle, ViewStyle, animated } from 'react-native'
import FastImage, { FastImageProps } from 'react-native-fast-image'
import { animated } from 'react-spring/native'
import { useSpring } from 'react-spring'
const AnimatedFastImage = animated(FastImage)
interface ImgStyle extends ImageStyle {
width: number | string
height: number | string
}
interface Props extends FastImageProps {
thumbnailSource?: FastImageProps['source']
style: ImgStyle
containerStyle?: ViewStyle
}
export const ProgressiveImage: FC<Props> = ({
thumbnailSource,
source,
style,
containerStyle,
...props
}) => {
const [thumbOpStyle, setThumbOpStyle] = useSpring(() => ({ opacity: 0, config: { duration: 500 } }))
const [imgOpStyle, setImgOpStyle] = useSpring(() => ({ opacity: 0, config: { duration: 500 } }))
function handleThumbnailLoad() {
setThumbOpStyle({ opacity: 1, config: { duration: 500 } })
}
function onImageLoad() {
setImgOpStyle({ opacity: 1, config: { duration: 500 } })
}
return (
<View style={[styles.container, { width: style.width, height: style.height }, containerStyle]}>
{thumbnailSource && (
<AnimatedFastImage
{...props}
source={thumbnailSource}
style={[style, thumbOpStyle]}
onLoad={handleThumbnailLoad}
blurRadius={1}
/>
)}
<AnimatedFastImage
{...props}
source={source}
style={[styles.imageOverlay, imgOpStyle, style]}
onLoad={onImageLoad}
/>
</View>
)
}
const styles = StyleSheet.create({
imageOverlay: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
top: 0,
},
container: {
backgroundColor: '#e1e4e8',
},
})