| 1 |
- {"version":3,"file":"accessibility.min.mjs","sources":["../../src/accessibleTarget.ts","../../src/AccessibilityManager.ts"],"sourcesContent":["import type { DisplayObject } from '@pixi/display';\n\nexport type PointerEvents = 'auto'\n| 'none'\n| 'visiblePainted'\n| 'visibleFill'\n| 'visibleStroke'\n| 'visible'\n| 'painted'\n| 'fill'\n| 'stroke'\n| 'all'\n| 'inherit';\n\nexport interface IAccessibleTarget\n{\n accessible: boolean;\n accessibleTitle: string;\n accessibleHint: string;\n tabIndex: number;\n _accessibleActive: boolean;\n _accessibleDiv: IAccessibleHTMLElement;\n accessibleType: string;\n accessiblePointerEvents: PointerEvents;\n accessibleChildren: boolean;\n renderId: number;\n}\n\nexport interface IAccessibleHTMLElement extends HTMLElement\n{\n type?: string;\n displayObject?: DisplayObject;\n}\n\n/**\n * Default property values of accessible objects\n * used by {@link PIXI.AccessibilityManager}.\n * @private\n * @function accessibleTarget\n * @memberof PIXI\n * @type {object}\n * @example\n * function MyObject() {}\n *\n * Object.assign(\n * MyObject.prototype,\n * PIXI.accessibleTarget\n * );\n */\nexport const accessibleTarget: IAccessibleTarget = {\n /**\n * Flag for if the object is accessible. If true AccessibilityManager will overlay a\n * shadow div with attributes set\n * @member {boolean}\n * @memberof PIXI.DisplayObject#\n */\n accessible: false,\n\n /**\n * Sets the title attribute of the shadow div\n * If accessibleTitle AND accessibleHint has not been this will default to 'displayObject [tabIndex]'\n * @member {?string}\n * @memberof PIXI.DisplayObject#\n */\n accessibleTitle: null,\n\n /**\n * Sets the aria-label attribute of the shadow div\n * @member {string}\n * @memberof PIXI.DisplayObject#\n */\n accessibleHint: null,\n\n /**\n * @member {number}\n * @memberof PIXI.DisplayObject#\n * @private\n * @todo Needs docs.\n */\n tabIndex: 0,\n\n /**\n * @member {boolean}\n * @memberof PIXI.DisplayObject#\n * @todo Needs docs.\n */\n _accessibleActive: false,\n\n /**\n * @member {boolean}\n * @memberof PIXI.DisplayObject#\n * @todo Needs docs.\n */\n _accessibleDiv: null,\n\n /**\n * Specify the type of div the accessible layer is. Screen readers treat the element differently\n * depending on this type. Defaults to button.\n * @member {string}\n * @memberof PIXI.DisplayObject#\n * @default 'button'\n */\n accessibleType: 'button',\n\n /**\n * Specify the pointer-events the accessible div will use\n * Defaults to auto.\n * @member {string}\n * @memberof PIXI.DisplayObject#\n * @default 'auto'\n */\n accessiblePointerEvents: 'auto',\n\n /**\n * Setting to false will prevent any children inside this container to\n * be accessible. Defaults to true.\n * @member {boolean}\n * @memberof PIXI.DisplayObject#\n * @default true\n */\n accessibleChildren: true,\n\n renderId: -1,\n};\n","import { DisplayObject } from '@pixi/display';\nimport { isMobile, removeItems } from '@pixi/utils';\nimport { accessibleTarget } from './accessibleTarget';\n\nimport type { Rectangle } from '@pixi/math';\nimport type { Container } from '@pixi/display';\nimport type { Renderer, AbstractRenderer, ExtensionMetadata } from '@pixi/core';\nimport { ExtensionType } from '@pixi/core';\nimport type { IAccessibleHTMLElement } from './accessibleTarget';\n\n// add some extra variables to the container..\nDisplayObject.mixin(accessibleTarget);\n\nconst KEY_CODE_TAB = 9;\n\nconst DIV_TOUCH_SIZE = 100;\nconst DIV_TOUCH_POS_X = 0;\nconst DIV_TOUCH_POS_Y = 0;\nconst DIV_TOUCH_ZINDEX = 2;\n\nconst DIV_HOOK_SIZE = 1;\nconst DIV_HOOK_POS_X = -1000;\nconst DIV_HOOK_POS_Y = -1000;\nconst DIV_HOOK_ZINDEX = 2;\n\n/**\n * The Accessibility manager recreates the ability to tab and have content read by screen readers.\n * This is very important as it can possibly help people with disabilities access PixiJS content.\n *\n * A DisplayObject can be made accessible just like it can be made interactive. This manager will map the\n * events as if the mouse was being used, minimizing the effort required to implement.\n *\n * An instance of this class is automatically created by default, and can be found at `renderer.plugins.accessibility`\n * @class\n * @memberof PIXI\n */\nexport class AccessibilityManager\n{\n /** @ignore */\n static extension: ExtensionMetadata = {\n name: 'accessibility',\n type: [\n ExtensionType.RendererPlugin,\n ExtensionType.CanvasRendererPlugin,\n ],\n };\n\n /** Setting this to true will visually show the divs. */\n public debug = false;\n\n /**\n * The renderer this accessibility manager works for.\n * @type {PIXI.CanvasRenderer|PIXI.Renderer}\n */\n public renderer: AbstractRenderer | Renderer;\n\n /** Internal variable, see isActive getter. */\n private _isActive = false;\n\n /** Internal variable, see isMobileAccessibility getter. */\n private _isMobileAccessibility = false;\n\n /** Button element for handling touch hooks. */\n private _hookDiv: HTMLElement;\n\n /** This is the dom element that will sit over the PixiJS element. This is where the div overlays will go. */\n private div: HTMLElement;\n\n /** A simple pool for storing divs. */\n private pool: IAccessibleHTMLElement[] = [];\n\n /** This is a tick used to check if an object is no longer being rendered. */\n private renderId = 0;\n\n /** The array of currently active accessible items. */\n private children: DisplayObject[] = [];\n\n /** Count to throttle div updates on android devices. */\n private androidUpdateCount = 0;\n\n /** The frequency to update the div elements. */\n private androidUpdateFrequency = 500; // 2fps\n\n /**\n * @param {PIXI.CanvasRenderer|PIXI.Renderer} renderer - A reference to the current renderer\n */\n constructor(renderer: AbstractRenderer | Renderer)\n {\n this._hookDiv = null;\n\n if (isMobile.tablet || isMobile.phone)\n {\n this.createTouchHook();\n }\n\n // first we create a div that will sit over the PixiJS element. This is where the div overlays will go.\n const div = document.createElement('div');\n\n div.style.width = `${DIV_TOUCH_SIZE}px`;\n div.style.height = `${DIV_TOUCH_SIZE}px`;\n div.style.position = 'absolute';\n div.style.top = `${DIV_TOUCH_POS_X}px`;\n div.style.left = `${DIV_TOUCH_POS_Y}px`;\n div.style.zIndex = DIV_TOUCH_ZINDEX.toString();\n\n this.div = div;\n this.renderer = renderer;\n\n /**\n * pre-bind the functions\n * @type {Function}\n * @private\n */\n this._onKeyDown = this._onKeyDown.bind(this);\n\n /**\n * pre-bind the functions\n * @type {Function}\n * @private\n */\n this._onMouseMove = this._onMouseMove.bind(this);\n\n // let listen for tab.. once pressed we can fire up and show the accessibility layer\n globalThis.addEventListener('keydown', this._onKeyDown, false);\n }\n\n /**\n * Value of `true` if accessibility is currently active and accessibility layers are showing.\n * @member {boolean}\n * @readonly\n */\n get isActive(): boolean\n {\n return this._isActive;\n }\n\n /**\n * Value of `true` if accessibility is enabled for touch devices.\n * @member {boolean}\n * @readonly\n */\n get isMobileAccessibility(): boolean\n {\n return this._isMobileAccessibility;\n }\n\n /**\n * Creates the touch hooks.\n * @private\n */\n private createTouchHook(): void\n {\n const hookDiv = document.createElement('button');\n\n hookDiv.style.width = `${DIV_HOOK_SIZE}px`;\n hookDiv.style.height = `${DIV_HOOK_SIZE}px`;\n hookDiv.style.position = 'absolute';\n hookDiv.style.top = `${DIV_HOOK_POS_X}px`;\n hookDiv.style.left = `${DIV_HOOK_POS_Y}px`;\n hookDiv.style.zIndex = DIV_HOOK_ZINDEX.toString();\n hookDiv.style.backgroundColor = '#FF0000';\n hookDiv.title = 'select to enable accessibility for this content';\n\n hookDiv.addEventListener('focus', () =>\n {\n this._isMobileAccessibility = true;\n this.activate();\n this.destroyTouchHook();\n });\n\n document.body.appendChild(hookDiv);\n this._hookDiv = hookDiv;\n }\n\n /**\n * Destroys the touch hooks.\n * @private\n */\n private destroyTouchHook(): void\n {\n if (!this._hookDiv)\n {\n return;\n }\n document.body.removeChild(this._hookDiv);\n this._hookDiv = null;\n }\n\n /**\n * Activating will cause the Accessibility layer to be shown.\n * This is called when a user presses the tab key.\n * @private\n */\n private activate(): void\n {\n if (this._isActive)\n {\n return;\n }\n\n this._isActive = true;\n\n globalThis.document.addEventListener('mousemove', this._onMouseMove, true);\n globalThis.removeEventListener('keydown', this._onKeyDown, false);\n\n this.renderer.on('postrender', this.update, this);\n this.renderer.view.parentNode?.appendChild(this.div);\n }\n\n /**\n * Deactivating will cause the Accessibility layer to be hidden.\n * This is called when a user moves the mouse.\n * @private\n */\n private deactivate(): void\n {\n if (!this._isActive || this._isMobileAccessibility)\n {\n return;\n }\n\n this._isActive = false;\n\n globalThis.document.removeEventListener('mousemove', this._onMouseMove, true);\n globalThis.addEventListener('keydown', this._onKeyDown, false);\n\n this.renderer.off('postrender', this.update);\n this.div.parentNode?.removeChild(this.div);\n }\n\n /**\n * This recursive function will run through the scene graph and add any new accessible objects to the DOM layer.\n * @private\n * @param {PIXI.Container} displayObject - The DisplayObject to check.\n */\n private updateAccessibleObjects(displayObject: Container): void\n {\n if (!displayObject.visible || !displayObject.accessibleChildren)\n {\n return;\n }\n\n if (displayObject.accessible && displayObject.interactive)\n {\n if (!displayObject._accessibleActive)\n {\n this.addChild(displayObject);\n }\n\n displayObject.renderId = this.renderId;\n }\n\n const children = displayObject.children;\n\n if (children)\n {\n for (let i = 0; i < children.length; i++)\n {\n this.updateAccessibleObjects(children[i] as Container);\n }\n }\n }\n\n /**\n * Before each render this function will ensure that all divs are mapped correctly to their DisplayObjects.\n * @private\n */\n private update(): void\n {\n /* On Android default web browser, tab order seems to be calculated by position rather than tabIndex,\n * moving buttons can cause focus to flicker between two buttons making it hard/impossible to navigate,\n * so I am just running update every half a second, seems to fix it.\n */\n const now = performance.now();\n\n if (isMobile.android.device && now < this.androidUpdateCount)\n {\n return;\n }\n\n this.androidUpdateCount = now + this.androidUpdateFrequency;\n\n if (!(this.renderer as Renderer).renderingToScreen)\n {\n return;\n }\n\n // update children...\n if (this.renderer._lastObjectRendered)\n {\n this.updateAccessibleObjects(this.renderer._lastObjectRendered as Container);\n }\n\n const { left, top, width, height } = this.renderer.view.getBoundingClientRect();\n const { width: viewWidth, height: viewHeight, resolution } = this.renderer;\n\n const sx = (width / viewWidth) * resolution;\n const sy = (height / viewHeight) * resolution;\n\n let div = this.div;\n\n div.style.left = `${left}px`;\n div.style.top = `${top}px`;\n div.style.width = `${viewWidth}px`;\n div.style.height = `${viewHeight}px`;\n\n for (let i = 0; i < this.children.length; i++)\n {\n const child = this.children[i];\n\n if (child.renderId !== this.renderId)\n {\n child._accessibleActive = false;\n\n removeItems(this.children, i, 1);\n this.div.removeChild(child._accessibleDiv);\n this.pool.push(child._accessibleDiv);\n child._accessibleDiv = null;\n\n i--;\n }\n else\n {\n // map div to display..\n div = child._accessibleDiv;\n let hitArea = child.hitArea as Rectangle;\n const wt = child.worldTransform;\n\n if (child.hitArea)\n {\n div.style.left = `${(wt.tx + (hitArea.x * wt.a)) * sx}px`;\n div.style.top = `${(wt.ty + (hitArea.y * wt.d)) * sy}px`;\n\n div.style.width = `${hitArea.width * wt.a * sx}px`;\n div.style.height = `${hitArea.height * wt.d * sy}px`;\n }\n else\n {\n hitArea = child.getBounds();\n\n this.capHitArea(hitArea);\n\n div.style.left = `${hitArea.x * sx}px`;\n div.style.top = `${hitArea.y * sy}px`;\n\n div.style.width = `${hitArea.width * sx}px`;\n div.style.height = `${hitArea.height * sy}px`;\n\n // update button titles and hints if they exist and they've changed\n if (div.title !== child.accessibleTitle && child.accessibleTitle !== null)\n {\n div.title = child.accessibleTitle;\n }\n if (div.getAttribute('aria-label') !== child.accessibleHint\n && child.accessibleHint !== null)\n {\n div.setAttribute('aria-label', child.accessibleHint);\n }\n }\n\n // the title or index may have changed, if so lets update it!\n if (child.accessibleTitle !== div.title || child.tabIndex !== div.tabIndex)\n {\n div.title = child.accessibleTitle;\n div.tabIndex = child.tabIndex;\n if (this.debug) this.updateDebugHTML(div);\n }\n }\n }\n\n // increment the render id..\n this.renderId++;\n }\n\n /**\n * private function that will visually add the information to the\n * accessability div\n * @param {HTMLElement} div -\n */\n public updateDebugHTML(div: IAccessibleHTMLElement): void\n {\n div.innerHTML = `type: ${div.type}</br> title : ${div.title}</br> tabIndex: ${div.tabIndex}`;\n }\n\n /**\n * Adjust the hit area based on the bounds of a display object\n * @param {PIXI.Rectangle} hitArea - Bounds of the child\n */\n public capHitArea(hitArea: Rectangle): void\n {\n if (hitArea.x < 0)\n {\n hitArea.width += hitArea.x;\n hitArea.x = 0;\n }\n\n if (hitArea.y < 0)\n {\n hitArea.height += hitArea.y;\n hitArea.y = 0;\n }\n\n const { width: viewWidth, height: viewHeight } = this.renderer;\n\n if (hitArea.x + hitArea.width > viewWidth)\n {\n hitArea.width = viewWidth - hitArea.x;\n }\n\n if (hitArea.y + hitArea.height > viewHeight)\n {\n hitArea.height = viewHeight - hitArea.y;\n }\n }\n\n /**\n * Adds a DisplayObject to the accessibility manager\n * @private\n * @param {PIXI.DisplayObject} displayObject - The child to make accessible.\n */\n private addChild<T extends DisplayObject>(displayObject: T): void\n {\n // this.activate();\n\n let div = this.pool.pop();\n\n if (!div)\n {\n div = document.createElement('button');\n\n div.style.width = `${DIV_TOUCH_SIZE}px`;\n div.style.height = `${DIV_TOUCH_SIZE}px`;\n div.style.backgroundColor = this.debug ? 'rgba(255,255,255,0.5)' : 'transparent';\n div.style.position = 'absolute';\n div.style.zIndex = DIV_TOUCH_ZINDEX.toString();\n div.style.borderStyle = 'none';\n\n // ARIA attributes ensure that button title and hint updates are announced properly\n if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)\n {\n // Chrome doesn't need aria-live to work as intended; in fact it just gets more confused.\n div.setAttribute('aria-live', 'off');\n }\n else\n {\n div.setAttribute('aria-live', 'polite');\n }\n\n if (navigator.userAgent.match(/rv:.*Gecko\\//))\n {\n // FireFox needs this to announce only the new button name\n div.setAttribute('aria-relevant', 'additions');\n }\n else\n {\n // required by IE, other browsers don't much care\n div.setAttribute('aria-relevant', 'text');\n }\n\n div.addEventListener('click', this._onClick.bind(this));\n div.addEventListener('focus', this._onFocus.bind(this));\n div.addEventListener('focusout', this._onFocusOut.bind(this));\n }\n\n // set pointer events\n div.style.pointerEvents = displayObject.accessiblePointerEvents;\n // set the type, this defaults to button!\n div.type = displayObject.accessibleType;\n\n if (displayObject.accessibleTitle && displayObject.accessibleTitle !== null)\n {\n div.title = displayObject.accessibleTitle;\n }\n else if (!displayObject.accessibleHint\n || displayObject.accessibleHint === null)\n {\n div.title = `displayObject ${displayObject.tabIndex}`;\n }\n\n if (displayObject.accessibleHint\n && displayObject.accessibleHint !== null)\n {\n div.setAttribute('aria-label', displayObject.accessibleHint);\n }\n\n if (this.debug) this.updateDebugHTML(div);\n\n displayObject._accessibleActive = true;\n displayObject._accessibleDiv = div;\n div.displayObject = displayObject;\n\n this.children.push(displayObject);\n this.div.appendChild(displayObject._accessibleDiv);\n displayObject._accessibleDiv.tabIndex = displayObject.tabIndex;\n }\n\n /**\n * Maps the div button press to pixi's InteractionManager (click)\n * @private\n * @param {MouseEvent} e - The click event.\n */\n private _onClick(e: MouseEvent): void\n {\n const interactionManager = this.renderer.plugins.interaction;\n const { displayObject } = e.target as IAccessibleHTMLElement;\n const { eventData } = interactionManager;\n\n interactionManager.dispatchEvent(displayObject, 'click', eventData);\n interactionManager.dispatchEvent(displayObject, 'pointertap', eventData);\n interactionManager.dispatchEvent(displayObject, 'tap', eventData);\n }\n\n /**\n * Maps the div focus events to pixi's InteractionManager (mouseover)\n * @private\n * @param {FocusEvent} e - The focus event.\n */\n private _onFocus(e: FocusEvent): void\n {\n if (!(e.target as Element).getAttribute('aria-live'))\n {\n (e.target as Element).setAttribute('aria-live', 'assertive');\n }\n\n const interactionManager = this.renderer.plugins.interaction;\n const { displayObject } = e.target as IAccessibleHTMLElement;\n const { eventData } = interactionManager;\n\n interactionManager.dispatchEvent(displayObject, 'mouseover', eventData);\n }\n\n /**\n * Maps the div focus events to pixi's InteractionManager (mouseout)\n * @private\n * @param {FocusEvent} e - The focusout event.\n */\n private _onFocusOut(e: FocusEvent): void\n {\n if (!(e.target as Element).getAttribute('aria-live'))\n {\n (e.target as Element).setAttribute('aria-live', 'polite');\n }\n\n const interactionManager = this.renderer.plugins.interaction;\n const { displayObject } = e.target as IAccessibleHTMLElement;\n const { eventData } = interactionManager;\n\n interactionManager.dispatchEvent(displayObject, 'mouseout', eventData);\n }\n\n /**\n * Is called when a key is pressed\n * @private\n * @param {KeyboardEvent} e - The keydown event.\n */\n private _onKeyDown(e: KeyboardEvent): void\n {\n if (e.keyCode !== KEY_CODE_TAB)\n {\n return;\n }\n\n this.activate();\n }\n\n /**\n * Is called when the mouse moves across the renderer element\n * @private\n * @param {MouseEvent} e - The mouse event.\n */\n private _onMouseMove(e: MouseEvent): void\n {\n if (e.movementX === 0 && e.movementY === 0)\n {\n return;\n }\n\n this.deactivate();\n }\n\n /** Destroys the accessibility manager */\n public destroy(): void\n {\n this.destroyTouchHook();\n this.div = null;\n\n globalThis.document.removeEventListener('mousemove', this._onMouseMove, true);\n globalThis.removeEventListener('keydown', this._onKeyDown);\n\n this.pool = null;\n this.children = null;\n this.renderer = null;\n }\n}\n"],"names":["accessibleTarget","accessible","accessibleTitle","accessibleHint","tabIndex","_accessibleActive","_accessibleDiv","accessibleType","accessiblePointerEvents","accessibleChildren","renderId","DisplayObject","mixin","AccessibilityManager","renderer","this","debug","_isActive","_isMobileAccessibility","pool","children","androidUpdateCount","androidUpdateFrequency","_hookDiv","isMobile","tablet","phone","createTouchHook","div","document","createElement","style","width","DIV_TOUCH_SIZE","height","position","top","DIV_TOUCH_POS_X","left","DIV_TOUCH_POS_Y","zIndex","toString","_onKeyDown","bind","_onMouseMove","globalThis","addEventListener","Object","defineProperty","prototype","get","_this","hookDiv","DIV_HOOK_SIZE","DIV_HOOK_POS_X","DIV_HOOK_POS_Y","backgroundColor","title","activate","destroyTouchHook","body","appendChild","removeChild","removeEventListener","on","update","_a","view","parentNode","deactivate","off","updateAccessibleObjects","displayObject","visible","interactive","addChild","i","length","now","performance","android","device","renderingToScreen","_lastObjectRendered","getBoundingClientRect","_b","viewWidth","viewHeight","resolution","sx","sy","child","removeItems","push","hitArea","wt","worldTransform","tx","x","a","ty","y","d","getBounds","capHitArea","getAttribute","setAttribute","updateDebugHTML","innerHTML","type","pop","borderStyle","navigator","userAgent","toLowerCase","indexOf","match","_onClick","_onFocus","_onFocusOut","pointerEvents","e","interactionManager","plugins","interaction","target","eventData","dispatchEvent","keyCode","movementX","movementY","destroy","extension","name","ExtensionType","RendererPlugin","CanvasRendererPlugin"],"mappings":"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"}
|