Skip to content

feat: #92 RankBarコンポーネントにランク画像表示を実装#99

Merged
Neon-straySheep merged 1 commit intodevelopfrom
feature/issue-92-rank-image-display
Feb 21, 2026
Merged

feat: #92 RankBarコンポーネントにランク画像表示を実装#99
Neon-straySheep merged 1 commit intodevelopfrom
feature/issue-92-rank-image-display

Conversation

@Neon-straySheep
Copy link
Contributor

RankBarコンポーネントにランク画像表示を実装

Issue: #92

📝 変更内容の概要

スキルツリー画面左上のRankBarコンポーネントにおいて、ランク番号(数字)の代わりにランク画像(rank_tree_0.pngrank_tree_9.png)を表示するように実装しました。

変更ファイル

  • frontend/src/features/skill-tree/components/RankBar.tsx
    • Next.js Imageコンポーネントをインポート
    • ランク番号表示を画像表示に置き換え
  • frontend/src/features/dashboard/types/index.ts
    • Rank型にrankNumber?: numberフィールドを追加(将来の拡張性のため)
  • frontend/src/features/dashboard/api/mock.ts
    • モックデータにrankNumberを追加(テスト用)

🔧 技術的な意思決定とトレードオフ

採用したアプローチ

Next.js Image コンポーネントの使用

  • メリット:
    • 自動的な画像最適化(WebP変換、レスポンシブ対応)
    • 遅延読み込み(lazy loading)によるパフォーマンス向上
    • Next.jsのベストプラクティスに準拠
  • デメリット:
    • 通常の<img>タグより若干重い(ただし最適化のメリットが上回る)
    • SSR/CSR環境で挙動が異なる場合がある('use client'で対処済み)

動的パス生成(テンプレートリテラル使用)

src={`/images/ranks/rank_tree_${tierIndex}.png`}
  • メリット:
    • コード量が少なく保守性が高い
    • tierIndex(0-9)の範囲内であれば自動的に適切な画像を選択
  • デメリット:
    • 画像が存在しない場合のフォールバック処理が未実装(現時点では全画像が存在するため問題なし)

却下した代替案

1. 静的import + switch文でマッピング

import rank0 from '/images/ranks/rank_tree_0.png';
// ... 9個のimport
  • 却下理由: コード量が増加し、保守性が低下するため

2. RankBadgeコンポーネントの再利用

  • 却下理由: RankBarは独自のスタイリング(ピクセルアート風、固定サイズ)を持っており、RankBadgeの汎用的な設計と合致しないため

🧪 テスト戦略と範囲

テスト済み項目

  • ✅ RankBarコンポーネントの画像表示(ローカル環境で目視確認)
  • ✅ TypeScriptコンパイルエラーがないこと(get_errorsで確認済み)
  • ✅ 画像パスが正しく生成されること(/images/ranks/rank_tree_${0-9}.png
  • ✅ 既存のスタイリング(ボーダー、シャドウ、背景色)が維持されること

意図的にテストしていないこと

  • 画像読み込み失敗時のフォールバック処理
    • 理由: 現時点では全ての画像(rank_tree_0.png ~ rank_tree_9.png)が存在するため
    • 将来的なリスク: 画像ファイルが削除された場合、壊れた画像アイコンが表示される
    • 対策案(後続issue推奨): onErrorハンドラーで数字表示にフォールバック
  • 異なる画面サイズでの表示確認
    • 理由: RankBarは固定サイズ(w-8 h-8)のため、レスポンシブ対応が不要
  • E2Eテスト
    • 理由: ハッカソンのスコープ外(手動テストで十分)

📸 動作確認の証拠

変更前(数字表示)

開発者ツールで確認した要素:

<div class="w-8 h-8 flex items-center justify-center text-xs font-bold shrink-0 bg-[#111827]" 
     style="border: 2px solid rgb(90, 191, 90); color: rgb(90, 191, 90);">
  2
</div>

変更後(画像表示)

<Image
  src="/images/ranks/rank_tree_2.png"
  alt="Rank 2 - 若木"
  width={32}
  height={32}
  className="object-contain"
  style={{ imageRendering: "pixelated" }}
/>

確認方法:

  1. フロントエンドサーバーを起動(npm run dev
  2. ダッシュボード画面(/dashboard)またはスキルツリー画面(/skills)にアクセス
  3. 左上のRankBarで画像が表示されていることを確認

🔐 セキュリティ考慮事項

  • tierIndexMath.min(Math.floor(progress * 10), 9)で0-9に制限されているため、パストラバーサルのリスクなし
  • ✅ 画像パスにユーザー入力は含まれていない(計算値のみ)
  • ✅ XSS攻撃のリスクなし(Reactが自動エスケープ)

📋 チェックリスト

  • Issue feat: #91 ランク画像を実装 #92 とリンクされている
  • Conventional Commits形式でコミットメッセージを記載
  • TypeScriptコンパイルエラーがない
  • 既存機能に影響を与えていない
  • 技術的な意思決定とトレードオフを明記
  • テスト範囲と意図的にテストしていないことを明記

🚀 今後の改善案(Optional)

  1. 画像読み込み失敗時のフォールバック処理
    • onErrorハンドラーで数字表示に戻す
  2. 画像の事前プリロード
    • priorityプロパティを使用して、初回表示を高速化
  3. アニメーション効果
    • ランクアップ時のアニメーション演出

関連Issue/PR


Closes #92

スキルツリー左側のRankBarコンポーネントで、ランク番号(数字)の代わりに
ランク画像(rank_tree_0.png~rank_tree_9.png)を表示するように変更。

【変更理由】
- 既存の画像アセットが未使用だった
- ユーザー体験向上のため視覚的な表現を強化

【技術的な実装】
- Next.js Image コンポーネントを使用して最適化
- tierIndex(0-9)を基に画像パスを動的生成
- レトロピクセル感を維持するため imageRendering を設定
@Neon-straySheep
Copy link
Contributor Author

スクリーンショット 2026-02-22 2 18 16

@Neon-straySheep Neon-straySheep merged commit dae6acc into develop Feb 21, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant