🌓

React Native 左右の View を比較するコンポーネント

2021/12/08に公開

正式な名称が未だにわからない左右を比較するコンポーネント

動作イメージ

https://snack.expo.dev/@tadaedo/beforeafter-example

実装

BeforeAfter.js
import React, { useRef } from 'react';
import { Animated, PanResponder, View } from 'react-native';

const BeforeAfter = (props) => {
    const { width, height, initPosition, left, right } = props;

    const clipWidth = new Animated.Value(initPosition);
    const panResponder = useRef(PanResponder.create({
        onMoveShouldSetPanResponder: (e, s) => true,
        onPanResponderMove: (e, s) => {
            clipWidth.setValue(e.nativeEvent.locationX);
        },
    })).current;

    return (
        <View style={{ width, height }} {...panResponder.panHandlers}>
            {right}
            <Animated.View style={{
                overflow: 'hidden',
                position: 'absolute',
                alignSelf: 'flex-start',
                width: clipWidth.interpolate({
                    inputRange: [0, 0, width, width],
                    outputRange: ["0%", "0%", "100%", "100%"]
                }),
            }}>
                {left}
            </Animated.View>
        </View>
    )
};

export default BeforeAfter;

使い方

  • width ・・・ 表示幅
  • height ・・・ 表示高さ
  • initPosition ・・・ 初期の境界線の位置
  • left ・・・ 左に表示する View
  • right ・・・ 右に表示する View
App.js
import React from 'react';
import { Image, SafeAreaView, StyleSheet, Text } from 'react-native';
import BeforeAfter from './BeforeAfter';

export default function App() {
  return (
    <SafeAreaView style={styles.container}>
      <BeforeAfter
        width={300}
        height={300}
        initPosition={150}
        left={
          <Text style={[styles.android, styles.text]}>Android</Text>
        }
        right={
          <Text style={[styles.ios, styles.text]}>iOS</Text>
        }
      />
      <BeforeAfter
        width={300}
        height={300}
        initPosition={150}
        left={
          <Image
            style={{ width: 300, height: 300 }}
            source={{ uri: 'https://picsum.photos/300/300' }} />
        }
        right={
          <Image
            style={{ width: 300, height: 300 }}
            source={{ uri: 'https://picsum.photos/300/400' }} />
        }
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
  },
  android: {
    backgroundColor: "#42f598",
  },
  ios: {
    backgroundColor: "#3096f0",
  },
  text: {
    width: 300,
    height: 300,
    lineHeight: 300,
    color: 'white',
    fontSize: 50,
    fontWeight: 'bold',
    textAlign: 'center',
  }
});

Discussion