React Native標準でドロップシャドウをつけたい場合スタイルで以下のように指定できます。
shadowColor: "black",
shadowOpacity: 0.3,
shadowOffset: { width: 0, height: 4 },
shadowRadius: 2,
ただしこれらはiOSの場合しか効かないため、Androidではelevationスタイルを指定する必要があります。
elevation: 3
これで浮き上がったように見せることはできますが、シャドウのスタイル詳細を指定できず影の色や位置・ぼかし方等を指定することができません。
代替としてreact-native-skiaを使ったシャドウの指定について説明します。
react-native-skiaでシャドウをつける場合、<Shadow />
を使います。対象のShapeのchildrenとして配置します。
<RoundedRect
x={margin}
y={margin}
{...buttonSize}
r={buttonSize.height / 2}
color="#39B1F0"
>
<Shadow dx={0} dy={4} blur={2} color="rgba(0, 0, 0, 0.3)" />
</RoundedRect>
以下のようにシャドウが表示されます。
試しにシャドウの設定を変更してみます。シャドウの色を少し変え、位置・ぼかし方を変えています。
<RoundedRect
x={margin}
y={margin}
{...buttonSize}
r={buttonSize.height / 2}
color="#39B1F0"
>
<Shadow dx={0} dy={0} blur={6} color="rgba(0, 0, 100, 0.5)" />
</RoundedRect>
ドロップシャドウだけでなく、Innerシャドウもつけることができます。 Shadows | React Native Skia
以下はボタン全体のコードです。
import { Canvas, RoundedRect, Shadow } from "@shopify/react-native-skia"
import { StyleSheet, Text, TouchableOpacity, View } from "react-native"
const buttonSize = { width: 200, height: 40 }
const margin = 8
export function ButtonWithShadow() {
const size = {
width: buttonSize.width + margin * 2,
height: buttonSize.height + margin * 2,
}
return (
<TouchableOpacity>
<View style={[styles.button, size]}>
<Canvas
style={[
styles.canvas,
{
...size,
},
]}
>
<RoundedRect
x={margin}
y={margin}
{...buttonSize}
r={buttonSize.height / 2}
color="#39B1F0"
>
<Shadow dx={0} dy={0} blur={6} color="rgba(0, 0, 100, 0.5)" />
</RoundedRect>
</Canvas>
<Text style={styles.titleText}>ボタン</Text>
</View>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
button: {
justifyContent: "center",
alignItems: "center",
},
canvas: { position: "absolute" },
titleText: { color: "white", fontWeight: "bold" },
})
skiaをつかう場合、Canvasの中で描画する必要があり、Canvasにwidthとheightを指定する必要があります。幅と高さが固定の場合は問題ありませんが、動的に指定したい場合はView
のonLayout
で幅と高さを取得する必要があります。
Text
についてはReact Nativeが用意したテキストシャドウ用のスタイルで指定可能です。Androidに関しても問題なく表示されます。
Text Style Props · React Native
Skiaでテキストを描画しようとするとフォントのロードに時間がかかってしまうので、通常のReact NativeのText
を使うことをおすすめします。