react-native-view-shotを使ってスクショをとる
Expo製メモアプリでボードだけをきれいに保存する方法
Expo で作ったアプリのボード部分だけ保存したかったんだ。view-shot を使えば一発でできるよ!
はじめに
現在 Expo(React Native)で以下のようなグラフィカルなメモアプリを開発しています。このアプリでボード部分だけのスクショを撮りたいと思った時に react-native-view-shot がベストな選択肢でした。
react-native-view-shot は、ネイティブのビュー階層をそのままキャプチャしてくれる便利なライブラリです。コンポーネントでラップするだけで任意の範囲を切り出せるので、キャンバスやホワイトボードのような UI と相性が抜群です。
いつも通りスクショを取るとこのような形になります。

react-native-view-shot を使った場合

導入
npx expo install expo-media-library
yarn add react-native-view-shot
expo-media-library は撮影した画像を端末のカメラロールへ保存するために使用します。ViewShot 単体でも URI は取得できますが、ユーザーが後から閲覧できる場所に残したい場合は MediaLibrary までセットで導入しておきましょう。
使い方
描画部分
とても直感的な使い方です。スクショ対象にしたい部分だけViewShotで囲みます。
このような形 ↓
<ViewShot
ref={boardShotRef} // 後で .capture() するための参照
style={styles.boardShot} // キャプチャ範囲のスタイル
options={{
format: "png", // 画像形式
quality: 1, // 画質100%
result: "tmpfile", // 一時ファイルパスで返す
}}
>
<GridBackground
onTransformChange={handleTransformChange}
onBackgroundTap={clearSelection}
initialViewState={initialViewState}
/>
</ViewShot>
ロジック部分
あとはhandleSaveBoardImageをボタンか何かで呼び出すだけです。
const handleSaveBoardImage = useCallback(async () => {
const uri = await boardShotRef.current.capture?.();
if (!uri) {
throw new Error("キャプチャに失敗しました。");
}
await MediaLibrary.saveToLibraryAsync(uri);
}, [isSavingBoardImage]);
capture() の戻り値はオプションに応じて変わりますが、result: "tmpfile" にしておくとファイルパスを扱えるので MediaLibrary と組み合わせやすくなります。保存処理の前後でローディング状態を管理したり、完了したらトースト通知を出すと UX がさらに向上します。
おわり
いかがだったでしょうか。今回の記事が少しでも参考になったら幸いです。
よければサイドバーからアプリをチェックしたり、メールで感想を送ってもらえたらうれしいです ☺️