iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Mobile Development

卡卡30天學 React Native系列 第 17

[ 卡卡 DAY 17 ] - React Native 用 Animated 來做簡單骨架屏

  • 分享至 

  • xImage
  •  

上一章節講了 Animated 的使用
我們運用 start() 來做個骨架屏唷!

製作 banner 骨架屏

  1. 引入 Animated
import { Animated } from 'react-native';
  1. 建立初始值
thumbnailAnimated = new Animated.Value(0); // 骨架屏的初始值
imageAnimated = new Animated.Value(0); // 真正banner的初始值
  1. 寫入 Animated.Image
// 骨架屏
<Animated.Image
    {...props}
    source={thumbnailSource}
    style={[style, { opacity: this.thumbnailAnimated }]}
    onLoad={this.handleThumbnailLoad}
    blurRadius={1}
/>
// banner
<Animated.Image
    {...props}
    source={source}
    style={[styles.imageOverlay, { opacity: this.imageAnimated }]}
    onLoad={this.onImageLoad}
/>
  1. 寫 handleThumbnailLoad 及 onImageLoad 的 function
// 骨架屏
handleThumbnailLoad = () => {
    Animated.timing(this.thumbnailAnimated, {
    toValue: 1
    }).start();
};
// banner
onImageLoad = () => {
    Animated.timing(this.imageAnimated, {
    toValue: 1,
    duration: 1000
    }).start();
};
  1. 做一個有 banner 的 screen 引入 ProgressiveImage
    <ProgressiveImage
        thumbnailSource={require('../asset/version-1.png')} // 骨架屏圖片
        source={img} // banner
        style={styles.bannerImg}
        resizeMode="cover"
        text="文字文字"
    />

ProgressiveImage.js

import React from 'react';
import { View, Animated, StyleSheet, Text } from 'react-native';

class ProgressiveImage extends React.Component {
    thumbnailAnimated = new Animated.Value(0);
    imageAnimated = new Animated.Value(0);
    handleThumbnailLoad = () => {
        Animated.timing(this.thumbnailAnimated, {
        toValue: 1
        }).start();
    };
    onImageLoad = () => {
        Animated.timing(this.imageAnimated, {
        toValue: 1,
        duration: 1000
        }).start();
    };
    render() {
        const { thumbnailSource, source, style, ...props } = this.props;
        return (
            <View style={styles.container}>
                <Animated.Image
                    {...props}
                    source={thumbnailSource}
                    style={[style, { opacity: this.thumbnailAnimated }]}
                    style={style}
                    onLoad={this.handleThumbnailLoad}
                    blurRadius={1}
                />
                <Animated.Image
                    {...props}
                    source={source}
                    style={[styles.imageOverlay, { opacity: this.imageAnimated }]}
                    onLoad={this.onImageLoad}
                />
                <Text style={[styles.bannerText, { lineHeight: 0 }]}>
                    {props.text}
                </Text>
            </View>
        );
    }
}
const styles = StyleSheet.create({
    imageOverlay: {
        position: 'absolute',
        left: 0,
        right: 0,
        bottom: 0,
        top: 0
    },
    container: {
        backgroundColor: '#e1e4e8'
    },
    bannerText: {
        color: "#fff",
        position: 'absolute',
        left: 15,
        bottom: 100
    }
});
export default ProgressiveImage;

運用 animated 的特性將圖片讀取後慢慢淡出,倘若沒有讀取成功,就會由骨架屏來顯示!!
倘若骨架屏不想有圖片只想有背景色
可忽略所有有包含 thumbnail 文字的 func or 變數
他會取 container 的背景顏色來當預設

Day18 done,請多多指教~


上一篇
[ 卡卡 DAY 16 ] - React Native Animated 入門 + useNativeDriver 好棒棒
下一篇
[ 卡卡 DAY 18 ] - React Native animated 來簡單使用 translate 效果
系列文
卡卡30天學 React Native31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言