2022-08-20

react-native-skiaでドロップシャドウをつける

React Nativeでのスタイル指定の問題

React Native標準でドロップシャドウをつけたい場合スタイルで以下のように指定できます。

  shadowColor: "black",
  shadowOpacity: 0.3,
  shadowOffset: { width: 0, height: 4 },
  shadowRadius: 2,

Shadow Props · React Native

ただしこれらはiOSの場合しか効かないため、Androidではelevationスタイルを指定する必要があります。

  elevation: 3

これで浮き上がったように見せることはできますが、シャドウのスタイル詳細を指定できず影の色や位置・ぼかし方等を指定することができません。

代替としてreact-native-skiaを使ったシャドウの指定について説明します。

react-native-skiaを使ったシャドウ指定

react-native-skiaでシャドウをつける場合、<Shadow />を使います。対象のShapeのchildrenとして配置します。

Shadows | React Native Skia

  <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>

以下のようにシャドウが表示されます。

シャドウをつけたボタン1

試しにシャドウの設定を変更してみます。シャドウの色を少し変え、位置・ぼかし方を変えています。

  <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>
シャドウをつけたボタン2

ドロップシャドウだけでなく、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を利用する場合の注意点

skiaをつかう場合、Canvasの中で描画する必要があり、Canvasにwidthとheightを指定する必要があります。幅と高さが固定の場合は問題ありませんが、動的に指定したい場合はViewonLayoutで幅と高さを取得する必要があります。

テキストのシャドウについて

TextについてはReact Nativeが用意したテキストシャドウ用のスタイルで指定可能です。Androidに関しても問題なく表示されます。

Text Style Props · React Native

Skiaでテキストを描画しようとするとフォントのロードに時間がかかってしまうので、通常のReact NativeのTextを使うことをおすすめします。

最終更新: 2022-09-02 01:05
筆者: @gaishimo 主にReact Nativeでのアプリ開発を行っています。
© 2021 Omoidasu, Inc. All rights reserved.