スケールアニメーション
要素のサイズを調整して拡大/縮小効果を作ります
スケールアニメーション
スケール(Scale)アニメーションは、要素のサイズを変更して拡大または縮小する効果を作ります。注目度を高めたり、視覚的な階層を表現する際に効果的です。
基本的な使い方
import { transition } from '@ssgoi/react';
import { scale } from '@ssgoi/react/transitions';
function Component() {
const [isVisible, setIsVisible] = useState(true);
return (
<div>
{isVisible && (
<div ref={transition({ key: 'scale-element', ...scale() })}>
スケールアニメーションが適用された要素
</div>
)}
</div>
);
}
オプション
interface ScaleOptions {
start?: number; // 開始サイズ倍率(デフォルト:0)
opacity?: number; // 開始透明度(デフォルト:0)
axis?: 'x' | 'y' | 'both'; // スケール方向(デフォルト:'both')
spring?: {
stiffness?: number; // スプリング強度(デフォルト:300)
damping?: number; // 減衰係数(デフォルト:30)
};
}
オプション説明
- start: アニメーション開始時のサイズ(0 = 0%、1 = 100%)
- opacity: 開始透明度(0-1)
- axis: スケールが適用される軸
'both'
: X軸とY軸の両方(デフォルト)'x'
: 横方向のみ'y'
: 縦方向のみ
- spring: スプリング物理設定
使用例
軸方向のスケール
X軸スケール(横方向拡張)
const scaleX = scale({
axis: 'x',
spring: { stiffness: 400, damping: 35 }
});
<div ref={transition({ key: 'scale-x', ...scaleX })}>
横方向にのみ拡張する要素
</div>
Y軸スケール(縦方向拡張)
const scaleY = scale({
axis: 'y',
spring: { stiffness: 400, damping: 35 }
});
<div ref={transition({ key: 'scale-y', ...scaleY })}>
縦方向にのみ拡張する要素
</div>
部分スケール
小さいサイズから始まる効果:
const partialScale = scale({
start: 0.5, // 50%のサイズから開始
opacity: 0.3, // 30%の透明度から開始
});
<div ref={transition({ key: 'partial-scale', ...partialScale })}>
半分のサイズから始まる要素
</div>
バウンス効果付きスケール
スプリング設定でバウンス効果を追加:
const bounceScale = scale({
spring: {
stiffness: 200, // 低い強度でバウンス
damping: 15 // 低い減衰で振動を増加
}
});
<div ref={transition({ key: 'bounce-scale', ...bounceScale })}>
弾むようなスケール効果
</div>
実用的な活用例
カードホバー効果
function Card() {
const [isHovered, setIsHovered] = useState(false);
return (
<div
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{isHovered && (
<div
ref={transition({
key: 'card-hover',
...scale({ start: 0.95, opacity: 0.8 })
})}
className="absolute inset-0 bg-blue-500/20 rounded-lg"
/>
)}
<div className="p-4">カード内容</div>
</div>
);
}
モーダル表示効果
function Modal({ isOpen, onClose }) {
return (
<>
{isOpen && (
<div className="fixed inset-0 flex items-center justify-center">
<div
ref={transition({
key: 'modal',
...scale({ start: 0.8, opacity: 0 })
})}
className="bg-white rounded-lg p-6 shadow-xl"
>
<h2>モーダルタイトル</h2>
<p>モーダル内容</p>
<button onClick={onClose}>閉じる</button>
</div>
</div>
)}
</>
);
}
アイコンアニメーション
function AnimatedIcon() {
const [isActive, setIsActive] = useState(false);
return (
<button onClick={() => setIsActive(!isActive)}>
{isActive ? (
<HeartFilledIcon
ref={transition({
key: 'heart-icon',
...scale({ start: 0, spring: { stiffness: 600, damping: 20 } })
})}
/>
) : (
<HeartOutlineIcon />
)}
</button>
);
}
パフォーマンス最適化
transform: scale()
はGPUアクセラレーションを使用し、優れたパフォーマンスを発揮します- レイアウト変更を起こさないため、リフローが発生しません
- 多くの要素に同時適用してもスムーズなアニメーションを維持します
パフォーマンスのヒント
// 良い例:transform使用
const goodScale = scale(); // transform: scale() 使用
// 避けるべき例:width/height直接変更
const badScale = {
in: (element) => ({
tick: (progress) => {
// リフロー発生!
element.style.width = `${progress * 100}px`;
element.style.height = `${progress * 100}px`;
}
})
};
アクセシビリティの考慮事項
<button
ref={transition({
key: 'accessible-button',
...scale({ start: 0.9 })
})}
aria-label="拡大するボタン"
className="focus:outline-none focus:ring-2"
>
クリックしてください
</button>
推奨される使用例
- ボタン/アイコン: クリックフィードバックやホバー効果
- カード/タイル: 選択状態やフォーカス表示
- モーダル/ポップアップ: 登場と退場のアニメーション
- 画像ギャラリー: サムネイル拡大効果
- チャート/グラフ: データ視覚化要素の強調