グリッドからプレーヤーへ

プロフィールページや検索結果では、投稿をサムネイルのグリッドで並べます。1 つをタップすると全画面で開き、そのまま残りをスワイプでき、プレーヤーを閉じたときには、見始めた投稿ではなく見終えた投稿の位置に戻っていることが求められます。

試してみる

どのバージョンも ./api をインポートしています。これはバックエンドの代わりで、posts はプロフィールや検索で読み込む投稿の一覧をプレーヤーの ContentItem の形にしたもの、thumbnailOf はグリッドのセルに表示する画像を選ぶ関数です。どちらも自分のデータに置き換えてください。

typescript
import { cdnUrl } from '@reelkit/example-data';

// Stands in for your backend: the posts a profile or a search result would
// load. Each one has the shape of `ContentItem` from the reel player of your
// framework, so the list goes to the player as it is.

export interface Post {
  id: string;
  media: {
    id: string;
    type: 'image' | 'video';
    src: string;
    poster?: string;
    aspectRatio: number;
  }[];
  author: { name: string; avatar: string };
  likes: number;
  description: string;
}

const kAuthors = ['Alex Johnson', 'Sarah Miller', 'Mike Chen', 'Emma Davis'];

const pad = (n: number) => String(n).padStart(2, '0');

export const posts: Post[] = Array.from({ length: 12 }, (_, i) => {
  const isVideo = i % 4 === 0;
  const n = (i % (isVideo ? 3 : 9)) + 1;
  return {
    id: `post-${i + 1}`,
    media: [
      isVideo
        ? {
            id: `video-${i + 1}`,
            type: 'video' as const,
            src: cdnUrl(`samples/videos/video-${pad(n)}.mp4`),
            poster: cdnUrl(`samples/videos/video-poster-${pad(n)}.jpg`),
            aspectRatio: 16 / 9,
          }
        : {
            id: `image-${i + 1}`,
            type: 'image' as const,
            src: cdnUrl(`samples/images/image-${pad(n)}.jpg`),
            aspectRatio: 2 / 3,
          },
    ],
    author: {
      name: kAuthors[i % kAuthors.length],
      avatar: cdnUrl(`samples/avatars/avatar-${pad((i % 8) + 1)}.jpg`),
    },
    likes: 120 + i * 37,
    description: `Post ${i + 1}`,
  };
});

/** The picture a grid cell shows: a video's poster, or the image itself. */
export const thumbnailOf = (post: Post) =>
  post.media[0].poster ?? post.media[0].src;
サンプルのメディアは reelkit.dev でしか使えません

cdnUrl が作るのは cdn.reelkit.dev へのリンクで、このサーバーは ReelKit のサイトにしかファイルを返しません。お使いのアプリでは画像も動画も読み込めないので、このファイルをコピーする前に media と avatar を自分のファイルに向けてください。

GridToPlayer.tsx
GridToPlayer.vue
grid-to-player.component.ts

投稿を開き、スワイプするか ↓ を何回か押してから Escape で閉じてください。グリッドは見終えた投稿までスクロールし、そのサムネイルにフォーカスが移ります。

仕組み

  • プレーヤーはタップした位置で開きます。 initialIndex にサムネイルのインデックスを渡し、content には一覧全体を渡すので、選んだ投稿のあとも続けてスワイプできます。どちらも React、Vue、Angular のプレーヤーのプロパティです。
  • グリッドは視聴者が止まった位置を知っています。 スライド切り替えのコールバックが視聴者のたどり着いた投稿をすべて知らせ、レシピは最後の 1 件を覚えておきます。プレーヤーのコールバック、イベント、出力に載っています。
  • フォーカスは正しいサムネイルに戻ります。 閉じるとき、プレーヤーは自分を開いた要素にフォーカスを戻します。これはプレーヤーのアクセシビリティ上の約束です。この戻しは閉じるハンドラーが動いたあとに行われるので、ハンドラーの中で設定したフォーカスは取り消されます。そこでレシピは 1 タスク待ってから、最後の投稿のサムネイルをスクロールして表示し、フォーカスを移します。
  • サムネイルはボタンです。 各セルはラベル付きの <button> なので、グリッドは Tab と Enter で操作でき、スクリーンリーダーは開く投稿を読み上げ、プレーヤーにはフォーカスを戻せる要素があります。プレーヤーのアクセシビリティの項で説明しているとおりです。
  • グリッドのセルに必要なのは動画ではなく画像です。 thumbnailOf は動画なら MediaItem のフィールドである poster を、画像ならそのまま使うので、グリッドが再生しない動画を読み込むことはありません。
  • 開いている投稿をアドレスバーに出したいなら。 URL 状態のプレーヤーは表示中の投稿を URL に入れるので、共有でき、戻るボタンで閉じられます。

次のステップ

  • ギャラリーのスライドショー - 同じグリッドから、スライドショーとして再生する Lightbox を開く
  • Reel Player - プレーヤーのプロパティ、スロット、部品のすべてReel Player - プレーヤーのプロパティ、スロット、部品のすべてReel Player - プレーヤーのプロパティ、スロット、部品のすべて