Loading...
Canvas displays are often seen as a "black box," with content that cannot be textified for screen readers to read aloud. To cater to people with different disabilities, features such as text extraction and keyboard navigation can be provided.
The best practices in the charting field can be found at Highcharts, which offers a wealth of practical examples worth emulating.
In G2, the functionality of text search can be implemented with the help of plugins.
First, install the @antv/g-plugin-a11y:
npm install @antv/g-plugin-rough-canvas-renderer --save
Then, import it into the plugin list:
import { Plugin } from '@antv/g-plugin-a11y';const plugin = new Plugin({ enableExtractingText: true });const chart = new Chart({container: 'container',plugins: [plugin],});
In some renderers (such as g-canvas / g-webgl / g-canvaskit), once text is drawn, the browser's built-in search functionality (Command + F
) cannot be used to locate matches, which is also not favorable for SEO.
In this example, after enabling enableExtractingText
, the text search functionality can be used:
import { Chart } from '@antv/g2';const plugin = new gPluginA11y.Plugin({ enableExtractingText: true });const labelFormatter = (d) => Math.abs(d) + (d < 0 ? 'BC' : d > 0 ? 'AC' : '');const left = (d) => d.end > -1500 && d.start > -3000;const chart = new Chart({container: 'container',width: 900,height: 1000,plugins: [plugin],});chart.options({type: 'interval',width: 900,height: 1000,data: {type: 'fetch',value: 'https://assets.antv.antgroup.com/g2/world-history.json',},encode: { x: 'civilization', y: ['start', 'end'], color: 'region' },transform: [{ type: 'sortX', by: 'y' },{ type: 'sortColor', by: 'y', reducer: 'min' },],scale: { color: { palette: 'set2' } },coordinate: { transform: [{ type: 'transpose' }] },axis: { x: false },labels: [{text: 'civilization',position: (d) => (left(d) ? 'left' : 'right'),textAlign: (d) => (left(d) ? 'end' : 'start'),dx: (d) => (left(d) ? -5 : 5),fontSize: 10,},],tooltip: {items: [{name: 'start',field: 'start',valueFormatter: labelFormatter,},{name: 'end',field: 'end',valueFormatter: labelFormatter,},],},});chart.render();
In the implementation, we added DOM elements within the canvas container to synchronize with the visible text in the canvas in real-time:
<divid="g-a11y-text-extractor-mask"style="position: absolute; inset: 0px; z-index: 99; pointer-events: none; user-select: none; overflow: hidden;"><divid="g-a11y-text-extractor-text-507"style="line-height: 1; position: absolute; white-space: pre; word-break: keep-all; color: transparent !important; font-family: sans-serif; font-size: 12px; transform-origin: 0px 0px; transform: translate(0px, 0px) translate(0px, -50%) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 215.856, 24, 0, 1);">East Asia</div></div>
Here are some considerations:
<foreignObject>
, the aforementioned DOM content will not be added.