React Native BlurView

Aboa·2023년 3월 21일
0
post-thumbnail

react-native에서 blur 효과를 주고싶은경우
https://github.com/Kureev/react-native-blur
라이브러리를 사용하는 방법도 있지만 해당 라이브러리는 베이스컬러지정을 못하거나
특정 OS, 특정 기기에서 과부하 이슈가 있는것을 확인하였으며 UI부분의 대한 이슈도 많기에 웹뷰로 구현하는 방식을 채택했습니다.
원본) https://gist.github.com/dutradotdev/50c82763fc621ab3c1bd5ba02180ce0d

react-native 0.64.0
react-native-webview 11.13.0

react-native-webview

npm install react-native-webview

첫 시도

import React from "react";
import { ColorValue, InteractionManager, StyleSheet, View } from "react-native";
import WebView from "react-native-webview";

export interface BlurViewProps {
	/**
	 * @example rgba(0, 0, 0, 0.5)
	 * @default "rgba(255, 255, 255, 0.8)"
	 */
	backgroundColor?: ColorValue;
	/**
	 * - px 단위
	 * @default 10
	 */
	blurRadius?: number;
}

const BlurView: React.VFC<BlurViewProps> = ({ backgroundColor, blurRadius }) => {
 
	return (
		<View
			style={[
				StyleSheet.absoluteFill,
				{
					backgroundColor: "#00000000",
					overflow: "hidden"
				}
			]}
		>
			<WebView
				style={{
					width: "100%",
					height: "100%",
					backgroundColor: "#00000000"
				}}
				originWhitelist={["*"]}
				overScrollMode='never'
				scrollEnabled={false}
				source={{
					html: `
						<html>
							<head>
								<meta name="viewport" content="initial-scale=1.0 maximum-scale=1.0" />
								<style>
									.blur {
										position: absolute;
										top: 0;
										right:0;
										bottom: 0;
										left: 0;
										background: ${String(backgroundColor)};
										-webkit-backdrop-filter: blur(${blurRadius}px);
										backdrop-filter: blur(${blurRadius}px);
									}
								</style>
							</head>
							<body>
								<div class="blur" />
							</body>
						</html>
					`
				}}
			/>
		</View>
	);
};

BlurView.defaultProps = {
	backgroundColor: "rgba(255, 255, 255, 0.8)",
	blurRadius: 10
};

export default BlurView;

해당 코드는 Android13에서 이슈가 발생했습니다.
BlurView에 크기가 작은경우 webview내부의 blur css가 적용되지않았습니다.

해결

import React from "react";
import { ColorValue, Dimensions, InteractionManager, StyleSheet, View } from "react-native";
import WebView from "react-native-webview";

export interface BlurViewProps {
	/**
	 * @example rgba(0, 0, 0, 0.5)
	 * @default "rgba(255, 255, 255, 0.8)"
	 */
	backgroundColor?: ColorValue;
	/**
	 * - px 단위
	 * @default 10
	 */
	blurRadius?: number;
}

const BlurView: React.VFC<BlurViewProps> = ({ backgroundColor, blurRadius }) => {
 
	return (
		<View
			style={[
				StyleSheet.absoluteFill,
				{
					backgroundColor: "#00000000",
					overflow: "hidden"
				}
			]}
		>
			<WebView
				style={{
					width: "100%",
					height: "100%",
					backgroundColor: "#00000000"
				}}
				originWhitelist={["*"]}
				overScrollMode='never'
				scrollEnabled={false}
				source={{
					html: `
						<html>
							<head>
								<meta name="viewport" content="initial-scale=1.0 maximum-scale=1.0" />
								<style>
									.blur {
										position: absolute;
										top: 0;
										right:0;
										bottom: 0;
										left: 0;
										height: ${Dimensions.get("screen").height}px;
										background: ${String(backgroundColor)};
										-webkit-backdrop-filter: blur(${blurRadius}px);
										backdrop-filter: blur(${blurRadius}px);
									}
								</style>
							</head>
							<body>
								<div class="blur" />
							</body>
						</html>
					`
				}}
			/>
		</View>
	);
};

BlurView.defaultProps = {
	backgroundColor: "rgba(255, 255, 255, 0.8)",
	blurRadius: 10
};

export default BlurView;
<style>
	.blur {
		position: absolute;
		top: 0;
		right:0;
		bottom: 0;
		left: 0;
		height: ${Dimensions.get("screen").height}px;
		background: ${String(backgroundColor)};
		-webkit-backdrop-filter: blur(${blurRadius}px);
		backdrop-filter: blur(${blurRadius}px);
	}
</style>

내용은 거의 동일하지만 height에 강제적으로 현재 디바이스 크기를 할당하여 내부컨텐츠를 늘려서 해결했습니다. 해결은 하였지만 너무 마음에 안드네요 혹시나 다른 해결방법이 있다면 공유해주시면 정말 감사하겠습니다.

예시

const App = () => {
	return (
		<SafeAreaView style={{ flex: 1, backgroundColor: "#FFF" }}>
			<View style={{ flex: 1, backgroundColor: "#FFF" }}>
				<View style={{ flex: 1, position: "relative" }}>
					<Image
						source={{
							uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/1200px-React-icon.svg.png"
						}}
						style={{ flex: 1 }}
						resizeMode='contain'
					/>
					<BlurView backgroundColor={"rgba(255, 255, 255, 0.4)"} blurRadius={5} />
				</View>
				<View style={{ height: 30, backgroundColor: "#000" }} />
				<View style={{ flex: 1 }}>
					<Image
						source={{
							uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/1200px-React-icon.svg.png"
						}}
						style={{ flexGrow: 1 }}
						resizeMode='contain'
					/>
				</View>
			</View>
		</SafeAreaView>
	);
};

0개의 댓글