Stories-Leiste

Die Reihe von Ringen oben in einem Feed: einer pro Person, leuchtend, solange sie etwas Neues hat, gedämpft, sobald der Nutzer alles gesehen hat. Ein Druck auf einen Ring öffnet die Stories bei der ersten, die noch nicht gesehen wurde, und der nächste Besuch weiß noch, wie weit der Nutzer gekommen ist, auch nach einem Neuladen.

Ausprobieren

Jede Version importiert ./api, das für dein Backend steht: groups sind die Personen, denen ein Nutzer folgt, mit den Stories, die jede gepostet hat, in der Form von StoriesGroup des Players. Ersetze es durch deinen eigenen Feed.

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

// Stands in for your backend: the people a viewer follows and the stories each
// one posted. Each entry has the shape of `StoriesGroup` from the stories
// player of your framework, so the list goes to the player as it is.

export interface Group {
  author: { id: string; name: string; avatar: string };
  stories: { id: string; mediaType: 'image'; src: string }[];
}

const kPeople = ['Alex', 'Sarah', 'Mike', 'Emma', 'Noah', 'Lena'];

// Uneven on purpose: a person with one story is watched to the end at once,
// one with three can be left part way and resumed.
const kStoryCounts = [3, 1, 2, 3, 1, 2];

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

const storyImage = (n: number) =>
  n <= 6
    ? cdnUrl(`samples/images/stories/story-00${n}.jpg`)
    : cdnUrl(`samples/images/image-${pad(n - 6)}.jpg`);

let nextImage = 1;

export const groups: Group[] = kPeople.map((name, i) => ({
  author: {
    id: `user-${i + 1}`,
    name,
    avatar: cdnUrl(`samples/avatars/avatar-${pad(i + 1)}.jpg`),
  },
  stories: Array.from({ length: kStoryCounts[i] }, (_, j) => ({
    id: `user-${i + 1}-story-${j + 1}`,
    mediaType: 'image' as const,
    src: storyImage(nextImage++),
  })),
}));
Die Beispielmedien funktionieren nur auf reelkit.dev

cdnUrl baut Links zu cdn.reelkit.dev, das seine Dateien nur an die Seiten von ReelKit ausliefert. In deiner App laden diese Avatare und Stories nicht, also lass avatar und src auf deine eigenen Dateien zeigen, bevor du diese Datei kopierst.

StoriesTray.tsx
Alex
Alex
Sarah
Sarah
Mike
Mike
Emma
Emma
Noah
Noah
Lena
Lena
StoriesTray.vue
Alex
Alex
Sarah
Sarah
Mike
Mike
Emma
Emma
Noah
Noah
Lena
Lena
stories-tray.component.ts
Alex
Alex
Sarah
Sarah
Mike
Mike
Emma
Emma
Noah
Noah
Lena
Lena

Schau dir jemanden bis zum Ende an und schließe den Player: Sein Ring wird gedämpft, der Fokus landet auf der zuletzt angesehenen Person, und beides übersteht ein Neuladen. „Forget what was seen“ fängt von vorn an.

Warum es funktioniert

  • Ein Controller merkt sich alles für beide. createStoriesViewedStateController wird einmal erstellt und geht als viewed an die Ringliste und den Player. Die Ringe lesen daraus, der Player trägt jede Story ein, die er zeigt, und der Controller hält das in localStorage unter storageKey, sodass ein Neuladen nichts ändert. Siehe den Abschnitt zum Merken des Gesehenen für React, Vue und Angular.
  • Der Player macht dort weiter, wo der Nutzer aufgehört hat. Mit viewed öffnet der Player eine Person bei ihrer ersten noch nicht gesehenen Story oder von vorn, sobald alles gesehen wurde. Das Rezept übergibt nur die Person, nie einen Story-Index; das beantwortet resumeStoryIndex des Controllers, siehe seine Referenz.
  • Ein Ring zeigt zwei Zustände. Leuchtend, solange noch etwas anzuschauen ist, gedämpft, sobald eine Person bis zum Ende angesehen wurde. Den Fortschritt innerhalb einer Person zeigt die Fortschrittsleiste des Players, nicht der Ring. Siehe StoriesRing.
  • Die Ringfarben folgen der Seite. Die beiden Zustände sind die Tokens --rk-stories-ring-active-gradient und --rk-stories-ring-viewed-color, und der gesehene Zustand ist standardmäßig ein blasses Weiß für eine dunkle Seite. Auf einer hellen Seite setzt du ihn auf .rk-stories-ring-list, wie diese Demo im hellen Theme, nicht auf :root: Das Desktop-Karussell des Players zeichnet Ringe mit denselben Tokens auf seinem dunklen Hintergrund. Die Tokens stehen in der Theming-Tabelle.
  • Keine zusätzliche Verdrahtung für den Controller. Der Player wird immer gerendert und mit isOpen geöffnet, also liest er den gespeicherten Zustand selbst, bevor er die erste Story wählt. Mountest du ihn nur, solange er offen ist, muss die Seite den Controller zuerst anhängen, wie die Referenz des Controllers erklärt.
  • Der Fokus kommt zum richtigen Ring zurück. Beim Schließen gibt der Player den Fokus an den Ring zurück, der ihn geöffnet hat, wie sein Abschnitt zur Barrierefreiheit beschreibt. Das passiert erst, nachdem der Close-Handler gelaufen ist, also wartet das Rezept einen Task, scrollt dann den Ring der zuletzt angesehenen Person ins Bild und fokussiert ihn.
  • Wo es sonst noch gespeichert werden kann. storage nimmt deinen eigenen Adapter, zum Beispiel einen Server, sodass das Gesehene dem Nutzer über Geräte hinweg folgt. Mit ttlMs läuft der Eintrag einer Person ab, und maxTracks begrenzt, wie viele Personen gespeichert werden. Sie stehen in der Konfiguration des Controllers.

Nächste Schritte

  • Endloser Feed - mehr laden, wenn der Nutzer sich dem Ende eines Feeds nähert
  • Stories Player - jedes Prop, jeder Slot und jeder Teil des PlayersStories Player - jedes Prop, jeder Slot und jeder Teil des PlayersStories Player - jedes Prop, jeder Slot und jeder Teil des Players