Skip to content

Instantly share code, notes, and snippets.

@cptvitamin
Created March 19, 2014 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cptvitamin/9633155 to your computer and use it in GitHub Desktop.
Save cptvitamin/9633155 to your computer and use it in GitHub Desktop.
Canvas Hit Regions and Focus Ring Demo
/**
* Canvas Hit Regions and Focus Ring Demo
*/
div.note {
margin-top: 1em;
margin-bottom: 1em;
}
.note > p:first-child { margin-top: 0 }
.note {
padding: .5em;
border-left-width: .5em;
border-left-style: solid;
}
div.note {
padding: 0.5em;
margin: 1em 0;
position: relative;
clear: both;
}
span.note { padding: .1em .5em .15em; }
.note {
border-color: #52e052;
background: #e9fbe9;
}
<h1>
Canvas Hit Regions and Focus Ring Demo
</h1>
<p class="note">
As of 18 MAR 2014 the following example only works in Mozilla Firefox Nightly
30.0a1 with the <code>canvas.focusring.enabled</code> and
<code>canvas.hitregions.enabled</code> flags set to <code>true</code>.
</p>
<canvas id="example" height="200" width="750">
<!-- Canvas Subtree acts as Shadow DOM that the browser maps to the platform accessibility API -->
<label for="OptionA"><input id="OptionA" type="checkbox"> Option A</label>
<label for="OptionB"><input id="OptionB" type="checkbox"> Option B</label>
</canvas>
function initDrawingArea() {
//Add the event listeners
document.getElementById('OptionA').addEventListener('focus', redraw, true);
document.getElementById('OptionB').addEventListener('focus', redraw, true);
document.getElementById('OptionA').addEventListener('blur', redraw, true);
document.getElementById('OptionB').addEventListener('blur', redraw, true);
document.getElementsByTagName('canvas')[0].addEventListener('change', redraw, true);
document.getElementsByTagName('canvas')[0].addEventListener('click', processClick, false);
// Draw the shadow DOM checkboxes on the canvas. Think model view controller
redraw();
}
/*
drawCheckbox
Draws a checkbox from a checkbox element in the shadow DOM
Parameters:
context - device Context
element - Checkbox element in the shadow DOM or <canvas> subtree
x - x coordinate position of the checkbox
y - y coordinate positon of the checkbox
*/
function drawCheckbox(context, element, x, y) {
context.save();
context.font = '15px sans-serif';
context.textAlign = 'left';
context.textBaseline = 'middle';
var metrics = context.measureText(element.parentNode.textContent);
context.beginPath();
context.strokeStyle = 'black';
context.rect(x-5, y-10, 15, 15);
context.stroke();
if (element.checked) {
context.fillStyle = 'black';
context.fill();
}
context.fillText(element.parentNode.textContent, x+10, y);
context.beginPath();
context.rect(x-7, y-12, 12 + metrics.width+2, 20);
if (document.activeElement == element)
context.drawFocusIfNeeded(element);
context.addHitRegion({control: element});
context.restore();
}
//Non-essential functions
function drawBase() { /* ... */ }
function drawAs() { /* ... */ }
function drawBs() { /* ... */ }
/*
redraw
Redraws the canvas rendering of the shadow DOM checkboxes
*/
function redraw() {
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
// erase the canvas
context.clearRect(0, 0, canvas.width, canvas.height);
//Draw checkboxes OptionA and OptionB
drawCheckbox(context, document.getElementById('OptionA'), 20, 40);
drawCheckbox(context, document.getElementById('OptionB'), 20, 60);
//These functions are nice to have but unnecessary
drawBase();
if (document.getElementById('OptionA').checked)
drawAs();
if (document.getElementById('OptionB').checked)
drawBs();
}
/*
processClick
Canvas event handler that processes canvas element checkbox clicks, and
updates the shadow DOM with the visual canvas.
Parameters:
event mouse click event
*/
function processClick(event){
/* Determine if the clicks are in the checkboxes and if so toggles the
corresponding canvas subtree checkbox and manage the focus */
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
var x = event.clientX - canvas.offsetLeft;
var y = event.clientY - canvas.offsetTop;
drawCheckbox(context, document.getElementById('OptionA'), 20, 40);
if (context.isPointInPath(x, y)) {
element = document.getElementById('OptionA');
document.getElementById('OptionA').checked = !(element.checked);
//Since the element was clicked, give it focus
element.focus();
}
drawCheckbox(context, document.getElementById('OptionB'), 20, 60);
if (context.isPointInPath(x, y)) {
element = document.getElementById('OptionB');
document.getElementById('OptionB').checked = !(element.checked);
//Since the element was clicked, give it focus
element.focus();
}
// Redraw the canvas
redraw();
}
initDrawingArea();
{"view":"split","fontsize":"100","seethrough":"","prefixfree":"1","page":"javascript"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment