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.padX Optional

Number. The horizontal padding. Defaults to 0.

properties.padY Optional

Number. The vertical padding. Defaults to 0.

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

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​.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.