Button([properties])
An accessible button. Supports screen readers and keyboard navigation using the Tab key. The button is automatically tracked by the pointer and accepts all pointer functions, but you will still need to call initPointer to have pointer events enabled.
Extends: Sprite
Button Parameters
-
properties
Optional Object. Properties of the button (in addition to all Sprite properties).
-
properties.text
Optional Object. Properties of Text which are used to create the textNode.
-
properties.disabled
Optional Boolean. Whether the button is disabled when created.
-
properties.padX
Optional Number. The horizontal padding. Defaults to
0
.-
properties.padY
Optional Number. The vertical padding. Defaults to
0
.-
properties.container
Optional HTMLElement. The HTMLElement that the HTMLButtonElement will be appended to.
-
properties.onEnable
Optional Function. Function called when the button is enabled.
-
properties.onDisable
Optional Function. Function called when the button is disabled.
-
properties.onFocus
Optional Function. Function called when the button is focused by the keyboard.
-
properties.onBlur
Optional Function. Function called when the button losses focus either by the pointer or keyboard.
Table of Contents
-
Properties
-
Methods
Basic Use
A button is essentially a Sprite with a Text child and added functionality to support keyboard interaction. To create a button, pass properties as you would with a Sprite and use the text
property to pass any Text properties. You can also pass any pointer event functions.
The size of the button will automatically be set as the width and height of the text or image, whichever is greater.
Button image courtesy of Kenney.
let { initPointer, setImagePath, load, imageAssets, Button } = kontra
// must call this to have pointer events work
initPointer();
setImagePath('assets/imgs/');
load('blue_button02.png', 'blue_button03.png').then(() => {
let button = Button({
// sprite properties
x: 300,
y: 100,
anchor: {x: 0.5, y: 0.5},
image: imageAssets['blue_button02'],
// text properties
text: {
text: 'Click me',
color: 'white',
font: '20px Arial, sans-serif',
anchor: {x: 0.5, y: 0.5}
},
// pointer events
onDown() {
this.image = imageAssets['blue_button03'];
this.y += 5;
},
onUp() {
this.image = imageAssets['blue_button02']
this.y -= 5;
}
});
// create a game loop to show updates to the button
let loop = kontra.GameLoop({
render() {
button.render();
}
});
// start the loop
loop.start();
});
import { initPointer, setImagePath, load, imageAssets, Button } from 'path/to/kontra.mjs'
// must call this to have pointer events work
initPointer();
setImagePath('assets/imgs/');
load('blue_button02.png', 'blue_button03.png').then(() => {
let button = Button({
// sprite properties
x: 300,
y: 100,
anchor: {x: 0.5, y: 0.5},
image: imageAssets['blue_button02'],
// text properties
text: {
text: 'Click me',
color: 'white',
font: '20px Arial, sans-serif',
anchor: {x: 0.5, y: 0.5}
},
// pointer events
onDown() {
this.image = imageAssets['blue_button03'];
this.y += 5;
},
onUp() {
this.image = imageAssets['blue_button02']
this.y -= 5;
}
});
// create a game loop to show updates to the button
let loop = kontra.GameLoop({
render() {
button.render();
}
});
// start the loop
loop.start();
});
import { initPointer, setImagePath, load, imageAssets, Button } from 'kontra';
// must call this to have pointer events work
initPointer();
setImagePath('assets/imgs/');
load('blue_button02.png', 'blue_button03.png').then(() => {
let button = Button({
// sprite properties
x: 300,
y: 100,
anchor: {x: 0.5, y: 0.5},
image: imageAssets['blue_button02'],
// text properties
text: {
text: 'Click me',
color: 'white',
font: '20px Arial, sans-serif',
anchor: {x: 0.5, y: 0.5}
},
// pointer events
onDown() {
this.image = imageAssets['blue_button03'];
this.y += 5;
},
onUp() {
this.image = imageAssets['blue_button02']
this.y -= 5;
}
});
// create a game loop to show updates to the button
let loop = kontra.GameLoop({
render() {
button.render();
}
});
// start the loop
loop.start();
});
Button States
A button has four possible states. You should use these states in the render() to have the button draw differently based on user input.
focused
- The button is focused by the keyboard or by calling the focus function.hovered
- The button is hovered by the mouse or by calling the onOver function.pressed
- The button is pressed with a mouse, touch, or keyboard event (such as Enter or Spacebar keys) or by calling the onDown function.disabled
- The button no longer accepts mouse or keyboard events.
let { initPointer, load, Button } = kontra
// must call this to have pointer events work
initPointer();
let button = Button({
// sprite properties
x: 300,
y: 100,
anchor: {x: 0.5, y: 0.5},
// text properties
text: {
text: 'Interact with me',
color: 'white',
font: '20px Arial, sans-serif',
anchor: {x: 0.5, y: 0.5}
},
// button properties
padX: 20,
padY: 10,
render() {
// focused by keyboard
if (this.focused) {
this.context.setLineDash([8,10]);
this.context.lineWidth = 3;
this.context.strokeStyle = 'red';
this.context.strokeRect(0, 0, this.width, this.height);
}
// pressed by mouse, touch, or enter/space on keyboard
if (this.pressed) {
this.textNode.color = 'yellow';
}
// hovered by mouse
else if (this.hovered) {
this.textNode.color = 'red';
canvas.style.cursor = 'pointer';
}
else {
this.textNode.color = 'white';
canvas.style.cursor = 'initial';
}
}
});
// create a game loop to show updates to the button
let loop = kontra.GameLoop({
render() {
button.render();
}
});
// start the loop
loop.start();
import { initPointer, load, Button } from 'path/to/kontra.mjs'
// must call this to have pointer events work
initPointer();
let button = Button({
// sprite properties
x: 300,
y: 100,
anchor: {x: 0.5, y: 0.5},
// text properties
text: {
text: 'Interact with me',
color: 'white',
font: '20px Arial, sans-serif',
anchor: {x: 0.5, y: 0.5}
},
// button properties
padX: 20,
padY: 10,
render() {
// focused by keyboard
if (this.focused) {
this.context.setLineDash([8,10]);
this.context.lineWidth = 3;
this.context.strokeStyle = 'red';
this.context.strokeRect(0, 0, this.width, this.height);
}
// pressed by mouse, touch, or enter/space on keyboard
if (this.pressed) {
this.textNode.color = 'yellow';
}
// hovered by mouse
else if (this.hovered) {
this.textNode.color = 'red';
canvas.style.cursor = 'pointer';
}
else {
this.textNode.color = 'white';
canvas.style.cursor = 'initial';
}
}
});
// create a game loop to show updates to the button
let loop = kontra.GameLoop({
render() {
button.render();
}
});
// start the loop
loop.start();
import { initPointer, load, Button } from 'kontra';
// must call this to have pointer events work
initPointer();
let button = Button({
// sprite properties
x: 300,
y: 100,
anchor: {x: 0.5, y: 0.5},
// text properties
text: {
text: 'Interact with me',
color: 'white',
font: '20px Arial, sans-serif',
anchor: {x: 0.5, y: 0.5}
},
// button properties
padX: 20,
padY: 10,
render() {
// focused by keyboard
if (this.focused) {
this.context.setLineDash([8,10]);
this.context.lineWidth = 3;
this.context.strokeStyle = 'red';
this.context.strokeRect(0, 0, this.width, this.height);
}
// pressed by mouse, touch, or enter/space on keyboard
if (this.pressed) {
this.textNode.color = 'yellow';
}
// hovered by mouse
else if (this.hovered) {
this.textNode.color = 'red';
canvas.style.cursor = 'pointer';
}
else {
this.textNode.color = 'white';
canvas.style.cursor = 'initial';
}
}
});
// create a game loop to show updates to the button
let loop = kontra.GameLoop({
render() {
button.render();
}
});
// start the loop
loop.start();
Accessibility
To be accessible to screen readers and keyboard users, the Button creates an HTMLButtonElement and appends it to the DOM. The button is given styles to be visually hidden and syncs keyboard events between the button element and Button functions. For example, calling focus()
on the Button will also focus the button element, and vis versa.
The button element is not ordered in the DOM, so if you need to create multiple buttons and want them to be in tab order, you'll need to create the buttons in the order they should be in (so their DOM nodes are appended in that order).
Button.blur()
Blur the button. Calls onBlur if passed.
Button.destroy()
Clean up the button by removing the HTMLButtonElement from the DOM.
Button.disable()
Disable the button. A disabled button will not longer render nor respond to pointer and keyboard events. Calls onDisable if passed.
Button.disabled
Boolean. If the button is disabled.
Button.enable()
Enable the button. Calls onEnable if passed.
Button.focus()
Focus the button. Calls onFocus if passed.
Button.focused
Boolean. If the button is focused.
Button.hovered
Boolean. If the button is hovered.
Button.node
HTMLButtonElement. The HTML button element associated with the button (used for accessibility). Typically you won't need to interact with the node
directly, but it can be useful to move its position in the DOM to better support accessible component design.
Button.onBlur()
Function called when then button is blurred. Override this function to have the button do something when blurred.
Button.onDisable()
Function called when then button is disabled. Override this function to have the button do something when disabled.
Button.onEnable()
Function called when then button is enabled. Override this function to have the button do something when enabled.
Button.onFocus()
Function called when then button is focused. Override this function to have the button do something when focused.
Button.padX
Number. The horizontal padding. This will be added to the width to give the final width of the button.
Button.padY
Number. The vertical padding. This will be added to the height to give the final height of the button.
Button.pressed
Boolean. If the button is pressed.
Button.text
String. The text property of the Text object.
Button.textNode
Text. Each Button creates a Text object and adds it as a child. The text
of the Text object is used as the accessible name of the HTMLButtonElement.