pixijs-accessibility

Par pixijs · pixijs-skills

Utilisez cette skill lors de l'ajout de la lecture d'écran et de la navigation clavier dans des applications PixiJS v8. Couvre les options d'AccessibilitySystem (`enabledByDefault`, `debug`, `activateOnTab`, `deactivateOnMouseMove`), les propriétés d'accessibilité par conteneur, la superposition shadow DOM, l'activation via le hook tactile mobile. Se déclenche sur : accessibility, a11y, screen reader, ARIA, keyboard navigation, tab order, AccessibilitySystem, `accessibleTitle`, `accessibleHint`, `tabIndex`, `accessibleChildren`.

npx skills add https://github.com/pixijs/pixijs-skills --skill pixijs-accessibility

Activez le lecteur d'écran et la navigation au clavier via le système AccessibilitySystem de PixiJS. Le système crée une couche DOM fantôme invisible positionnée sur les conteneurs accessibles afin que la technologie d'assistance puisse les découvrir et les activer.

Quick Start

const button = new Sprite(await Assets.load("button.png"));
button.accessible = true;
button.accessibleTitle = "Play game";
button.accessibleHint = "Starts a new game session";
button.eventMode = "static";
button.tabIndex = 0;
app.stage.addChild(button);

app.renderer.accessibility.setAccessibilityEnabled(true);

button.on("pointertap", () => startGame());

Skills connexes : pixijs-events (gestionnaires pointer/tap), pixijs-scene-dom-container (éléments HTML sur canvas), pixijs-application (options d'initialisation).

Points clés :

  • Par défaut, le système s'active uniquement après que l'utilisateur appuie sur Tab. Définissez enabledByDefault: true lors de l'initialisation de l'Application pour une activation immédiate.
  • Sur mobile, le système crée un hook tactile masqué ; le focus du lecteur d'écran active l'accessibilité pour toute la session.
  • L'AccessibilitySystem nécessite le thread principal ; il n'est pas disponible dans un Web Worker.

Core Patterns

Propriétés accessible des conteneurs

import { Container, Sprite } from "pixi.js";

const container = new Container();
container.accessible = true;
container.accessibleTitle = "Navigation menu";
container.accessibleHint = "Contains links to other pages";
container.eventMode = "static"; // required for custom tabIndex to apply
container.tabIndex = 0;
container.accessibleType = "div"; // defaults to 'button'

const sprite = new Sprite();
sprite.accessible = true;
sprite.accessibleTitle = "Close dialog";
sprite.accessibleText = "X"; // text content of the shadow div
sprite.eventMode = "static";
sprite.tabIndex = 1;

Propriétés disponibles sur tout Container :

  • accessible (boolean) - active la div overlay accessible
  • accessibleTitle (string) - définit l'attribut title sur la div fantôme
  • accessibleHint (string) - définit l'attribut aria-label
  • accessibleText (string) - définit le contenu texte interne de la div fantôme
  • accessibleType (string) - balise HTML pour l'élément fantôme, par défaut 'button'
  • tabIndex (number) - ordre de tabulation pour la navigation au clavier (appliqué uniquement quand interactive est true / eventMode est 'static' ou 'dynamic')
  • accessibleChildren (boolean, par défaut true) - quand false, empêche les conteneurs enfants d'être accessibles
  • accessiblePointerEvents (string) - valeur CSS pointer-events sur la div fantôme

Ordre de tabulation personnalisé

Attribuez à chaque conteneur accessible un tabIndex pour contrôler l'ordre dans lequel la technologie d'assistance les parcourt. Les nombres plus élevés viennent plus tard ; les nombres égaux reviennent à l'ordre du graphe de scène.

menuButton.accessible = true;
menuButton.eventMode = "static";
menuButton.tabIndex = 1;

playButton.accessible = true;
playButton.eventMode = "static";
playButton.tabIndex = 2;

settingsButton.accessible = true;
settingsButton.eventMode = "static";
settingsButton.tabIndex = 3;

tabIndex est transmis à la div fantôme uniquement quand le conteneur est interactive (eventMode est 'static' ou 'dynamic'). Sans cela, le système limite le tabIndex de la div à 0, et l'ordre que vous définissez est ignoré.

Contrôle programmatique

import { Application } from "pixi.js";

const app = new Application();
await app.init({ width: 800, height: 600 });

// Enable accessibility at runtime
app.renderer.accessibility.setAccessibilityEnabled(true);

// Check current state
console.log(app.renderer.accessibility.isActive);
console.log(app.renderer.accessibility.isMobileAccessibility);

// Full init options:
await app.init({
  accessibilityOptions: {
    enabledByDefault: true, // activate immediately (default: false)
    debug: true, // makes overlay divs visible (default: false)
    activateOnTab: true, // Tab key activates system (default: true)
    deactivateOnMouseMove: false, // stay active when mouse moves (default: true)
  },
});

Le système peut aussi être configuré via des options statiques par défaut avant de créer l'Application :

import { AccessibilitySystem, Application } from "pixi.js";

AccessibilitySystem.defaultOptions.enabledByDefault = true;
AccessibilitySystem.defaultOptions.deactivateOnMouseMove = false;

const app = new Application();
await app.init();

Traiter les interactions accessibles

import { Sprite } from "pixi.js";

const button = new Sprite();
button.eventMode = "static";
button.accessible = true;
button.accessibleTitle = "Submit form";
button.tabIndex = 0;

// Screen readers trigger click/tap events through the shadow DOM element
button.on("pointertap", () => {
  submitForm();
});

Quand l'accessibilité est active et qu'un utilisateur active une div fantôme (via la touche Entrée/Espace ou une action du lecteur d'écran), le système distribue les événements fédérés click, pointertap, et tap au conteneur correspondant. Le focus sur la div fantôme distribue mouseover, et la perte de focus distribue mouseout. À la fois eventMode et accessible doivent être définis pour un support clavier + pointeur complet.

Common Mistakes

[MEDIUM] Attendre que l'accessibilité soit active sans appui sur la touche Tab

L'AccessibilitySystem ne crée sa couche DOM que lorsque l'utilisateur appuie sur Tab (ou, sur mobile, met le focus sur le hook tactile). Si votre application a besoin d'accessibilité immédiatement :

const app = new Application();
await app.init({
  accessibilityOptions: {
    enabledByDefault: true,
  },
});

Ou au runtime :

app.renderer.accessibility.setAccessibilityEnabled(true);

Sans l'un de ces éléments, les outils de test d'accessibilité automatisés ne trouveront pas les éléments overlay.

[MEDIUM] Définir accessible sans accessibleTitle

Incorrect :

const sprite = new Sprite();
sprite.accessible = true;
// no title or hint set

Correct :

const sprite = new Sprite();
sprite.accessible = true;
sprite.accessibleTitle = "Play button";
sprite.accessibleHint = "Click to start the game";

Un conteneur avec accessible = true mais sans accessibleTitle ou accessibleHint obtient un titre de secours "container {tabIndex}". Les lecteurs d'écran annonceront ce label générique sans contexte utile. Fournissez toujours au moins accessibleTitle.

[MEDIUM] L'accessibilité se désactive quand on bouge la souris

Par défaut, deactivateOnMouseMove est true. Tout mouvement de souris après l'activation par Tab désactivera l'overlay. C'est intentionnel (suppose que les utilisateurs au clavier seul n'utilisent pas une souris), mais cela rend les tests à la souris frustrateurs.

await app.init({
  accessibilityOptions: {
    deactivateOnMouseMove: false,
  },
});

[MEDIUM] Ne pas importer l'extension accessibility dans les builds personnalisés

Quand vous utilisez skipExtensionImports: true pour un build personnalisé, l'extension accessibility n'est pas automatiquement enregistrée. Vous devez l'importer explicitement :

import "pixi.js/accessibility";
import { Application } from "pixi.js";

const app = new Application();
await app.init({ skipExtensionImports: true });

Sans cet import, app.renderer.accessibility sera undefined et aucune couche shadow DOM ne sera créée.

API Reference

Skills similaires