React Native ネイティブグラデーションマスクコンポーネント
美しいフェードエフェクト、リストマスク、スムーズなグラデーショントランジションを、ネイティブパフォーマンスと Reanimated アニメーションサポートで実現。
| iOS | Android |
![]() |
![]() |
| 特徴 | 説明 |
|---|---|
| クロスプラットフォーム | iOS、Android、Web 対応 |
| ネイティブパフォーマンス | iOS: CAGradientLayer • Android: Bitmap + PorterDuff • Web: CSS mask-image |
| Reanimated 対応 | AnimatedGradientMaskView で 60fps のスムーズなマスクアニメーション |
| 柔軟な設定 | カスタムカラー、位置、方向、マスク強度 |
| TypeScript | 完全な型定義付き |
npm install react-native-gradient-maskyarn add react-native-gradient-mask| 依存関係 | バージョン |
|---|---|
| Expo SDK | 50+ |
| React Native | 0.73+ |
| react-native-reanimated | >= 3.0.0 (オプション) |
iOS
cd ios && pod installAndroid
追加設定不要。オートリンクが有効です。
import { processColor } from 'react-native';
import { GradientMaskView } from 'react-native-gradient-mask';
const colors = [
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,1)'),
];
export default function App() {
return (
<GradientMaskView
colors={colors}
locations={[0, 1]}
direction="top"
style={{ flex: 1 }}
>
<YourContent />
</GradientMaskView>
);
}| コンポーネント | 説明 |
|---|---|
GradientMaskView |
基本グラデーションマスクコンポーネント |
AnimatedGradientMaskView |
Reanimated アニメーション対応グラデーションマスク |
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
colors |
(number | null)[] |
はい | - | グラデーションカラー(processColor() を使用) |
locations |
number[] |
はい | - | カラー位置 (0-1) |
direction |
'top' | 'bottom' | 'left' | 'right' |
いいえ | 'top' |
グラデーション方向 |
maskOpacity |
number |
いいえ | 1 |
マスク強度 (0-1) |
style |
ViewStyle |
いいえ | - | コンテナスタイル |
children |
ReactNode |
いいえ | - | マスクを適用するコンテンツ |
GradientMaskView と同じですが、maskOpacity はアニメーション制御用の SharedValue<number> を受け付けます。
| 方向 | 効果 |
|---|---|
top |
上部が透明 → 下部が不透明 |
bottom |
下部が透明 → 上部が不透明 |
left |
左側が透明 → 右側が不透明 |
right |
右側が透明 → 左側が不透明 |
import { processColor } from 'react-native';
import { GradientMaskView } from 'react-native-gradient-mask';
const colors = [
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,0.5)'),
processColor('rgba(0,0,0,1)'),
];
function FadeExample() {
return (
<GradientMaskView
colors={colors}
locations={[0, 0.3, 1]}
direction="top"
style={{ flex: 1 }}
>
<ScrollView>
<Text>フェードエフェクト付きコンテンツ</Text>
</ScrollView>
</GradientMaskView>
);
}import { processColor } from 'react-native';
import { AnimatedGradientMaskView } from 'react-native-gradient-mask';
import { useSharedValue, withTiming } from 'react-native-reanimated';
function AnimatedExample() {
const maskOpacity = useSharedValue(0);
const showMask = () => {
maskOpacity.value = withTiming(1, { duration: 600 });
};
const hideMask = () => {
maskOpacity.value = withTiming(0, { duration: 400 });
};
return (
<AnimatedGradientMaskView
colors={[
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,1)'),
]}
locations={[0, 1]}
maskOpacity={maskOpacity}
style={{ flex: 1 }}
>
<YourContent />
</AnimatedGradientMaskView>
);
}import { useMemo, useCallback, useRef } from 'react';
import { processColor } from 'react-native';
import { FlashList } from '@shopify/flash-list';
import { AnimatedGradientMaskView } from 'react-native-gradient-mask';
import { useSharedValue, withTiming, cancelAnimation, Easing } from 'react-native-reanimated';
function ChatList({ messages }) {
const maskOpacity = useSharedValue(0);
const isAtBottomRef = useRef(false);
const maskColors = useMemo(() => [
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,0.2)'),
processColor('rgba(0,0,0,0.6)'),
processColor('rgba(0,0,0,0.9)'),
processColor('rgba(0,0,0,1)'),
], []);
const handleScroll = useCallback((e) => {
const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
const distanceFromBottom = contentSize.height - contentOffset.y - layoutMeasurement.height;
const isAtBottom = distanceFromBottom <= 30;
if (isAtBottom !== isAtBottomRef.current) {
isAtBottomRef.current = isAtBottom;
cancelAnimation(maskOpacity);
maskOpacity.value = withTiming(isAtBottom ? 1 : 0, {
duration: isAtBottom ? 600 : 400,
easing: isAtBottom ? Easing.in(Easing.quad) : Easing.out(Easing.quad),
});
}
}, []);
return (
<AnimatedGradientMaskView
colors={maskColors}
locations={[0, 0.42, 0.45, 0.48, 0.5, 1]}
direction="top"
maskOpacity={maskOpacity}
style={{ flex: 1 }}
>
<FlashList
data={messages}
renderItem={({ item }) => <MessageItem item={item} />}
onScroll={handleScroll}
scrollEventThrottle={16}
/>
</AnimatedGradientMaskView>
);
}// ✅ 正しい
const colors = [
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,1)'),
];
// ❌ 間違い - 動作しません
const colors = [
'rgba(0,0,0,0)',
'rgba(0,0,0,1)',
];const maskColors = useMemo(() => [
processColor('rgba(0,0,0,0)'),
processColor('rgba(0,0,0,1)'),
], []);import { cancelAnimation } from 'react-native-reanimated';
// 新しいアニメーションを開始する前に前のアニメーションをキャンセル
cancelAnimation(maskOpacity);
maskOpacity.value = withTiming(newValue, { duration: 300 });| プラットフォーム | 実装 | 状態 |
|---|---|---|
| iOS | CAGradientLayer |
✅ |
| Android | Bitmap + LinearGradient + PorterDuff |
✅ |
| Web | CSS mask-image + linear-gradient |
✅ |
このライブラリは Anini のために開発されました — スムーズでネイティブ品質のユーザー体験を提供する AI チャットコンパニオンアプリです。
このプロジェクトは GAZAI がスポンサーです — 革新的な AI 駆動アプリケーションを構築しています。
MIT © DaYuan Lin (CS6)
React Native コミュニティのために ❤️ を込めて作りました

