Creating a canvas to draw on using Typescript (2023)

7 minute read

A quick tutorial on how to create a small web application to handle the userdrawing on HTML canvas elements.

Introduction

The aim of this tutorial is to demonstrate how to work with canvaselements. This will be done by creating a simple web page and usingtypescript to write the code that powers the logic of the page, which willallow the user to draw on the canvas element like is possible in a trivialpaint application.

Why Typescript

I’m not an expert in web development, so I really appreciate the statictyping available in Typescript. Combined with VS Code’s Intellisense forTypescript, it makes it fairly easy to start writing new functionality anddiscovering new APIs while being reasonably certain of its correctness.

The files

There are three files needed for this demo:

  • tsconfig.json - configures the typescript compiler
  • index.html - simple HTML page with a canvas and button element
  • main.ts - the typescript file that we will write and compile

tsconfig.json

This file is relatively straightforward. It sets the target for the compiledJavascript code (ES5), turns on source map for easier debugging, and a fewother relatively inconsequential things. If you’d like to read more, a niceexplanation of tsconfig.json is available here and a page explainingthe compiler options is available here.

{ "compilerOptions": { "target": "es5", "sourceMap": true, "lib": [ "es5", "dom" ], "noUnusedLocals": true, "module": "commonjs" }}
(Video) Learn HTML5 Canvas By Creating A Drawing App | HTML Canvas Tutorial

index.html

Another relatively straightforward file, the contents index.html will serveas a foreshadowing of what we’re going to make.

<html><head> <title>Canvas demo</title></head><body> <canvas id="canvas" width="490" height="490" style="border: 1px solid black;"> </canvas> <p id="clear">clear</p> <script src="main.js"></script></body></html>

This creates a canvas element (with the aptly-named id, canvas). It alsocreates a text label (the p element with id clear) that will clear thedrawing area when clicked.

main.ts

Finally, we start writing the main file. We begin with the skeleton of theclass that is going to contain the functionality:

class DrawingApp {}new DrawingApp();
(Video) Canvas Basics - Drawing Rectangles - ReactJS, TypeScript Tutorial #1

DrawingApp is the name of the class we’re going to fill in. At the end, youcan see we instantiate a new class. Upon instantiation, we will find therelevant DOM elements and register event handlers for the events that we’reinterested in.

This is done by writing a constructor for the class. Add the followingsnippet to the body of the DrawingApp class:

private canvas: HTMLCanvasElement;private context: CanvasRenderingContext2D;private paint: boolean;private clickX: number[] = [];private clickY: number[] = [];private clickDrag: boolean[] = [];constructor() { let canvas = document.getElementById('canvas') as HTMLCanvasElement; let context = canvas.getContext("2d"); context.lineCap = 'round'; context.lineJoin = 'round'; context.strokeStyle = 'black'; context.lineWidth = 1; this.canvas = canvas; this.context = context; this.redraw(); this.createUserEvents();}

The constructor method is called automatically when instantiating theclass, the same as constructor methods in other OOP languages. In theconstructor, the first thing we do is get a handle to the element that hascanvas as the id. We then get a 2D rendering context from the canvas. Othermodes are also available. For the 2D context, we then set some defaultsfor our drawing app. Finally, we store the handles in the class’s variablesand call a couple of methods that we will define next (add these to theclass):

private createUserEvents() { let canvas = this.canvas; canvas.addEventListener("mousedown", this.pressEventHandler); canvas.addEventListener("mousemove", this.dragEventHandler); canvas.addEventListener("mouseup", this.releaseEventHandler); canvas.addEventListener("mouseout", this.cancelEventHandler); canvas.addEventListener("touchstart", this.pressEventHandler); canvas.addEventListener("touchmove", this.dragEventHandler); canvas.addEventListener("touchend", this.releaseEventHandler); canvas.addEventListener("touchcancel", this.cancelEventHandler); document.getElementById('clear') .addEventListener("click", this.clearEventHandler);}private redraw() { let clickX = this.clickX; let context = this.context; let clickDrag = this.clickDrag; let clickY = this.clickY; for (let i = 0; i < clickX.length; ++i) { context.beginPath(); if (clickDrag[i] && i) { context.moveTo(clickX[i - 1], clickY[i - 1]); } else { context.moveTo(clickX[i] - 1, clickY[i]); } context.lineTo(clickX[i], clickY[i]); context.stroke(); } context.closePath();}
(Video) Canvas Basics - Drawing Polygons and Circles- ReactJS, TypeScript Tutorial #2

createUserEvents does what the name says – it sets up the handlers for thecanvas events that we’re interested in. We register for both mouse and touchevents so that the app can work not only on normal computers but on mobiledevices as well. redraw is a little bit more complicated. The method usesall the stored information about where the user clicks and drags the mouseand uses that to draw on the canvas element. If the user was dragging(clicking and moving the cursor at the same time), we draw a line through allthe points one-by-one. However, if they just clicked in a spot, we draw apoint one pixel wide. The stored state of the user’s action is managed by theaddClick and clearCanvas methods:

private addClick(x: number, y: number, dragging: boolean) { this.clickX.push(x); this.clickY.push(y); this.clickDrag.push(dragging);}private clearCanvas() { this.context .clearRect(0, 0, this.canvas.width, this.canvas.height); this.clickX = []; this.clickY = []; this.clickDrag = [];}

These functions are used to add to and clear the state, respectively, of the user’s actions on the canvas element. We store the X and Y coordinates along with a boolean representing whether the user was in the middle of dragging the cursor.

When the user does perform an action on the canvas (other than simply moving the cursor over it), our event handlers will get triggered, which we registered with the browser with the createUserEvents method. We’ll start with the three simple handlers:

private clearEventHandler = () => { this.clearCanvas();}private releaseEventHandler = () => { this.paint = false; this.redraw();}private cancelEventHandler = () => { this.paint = false;}
(Video) LETS BUILD A DRAWING APPLICATION USING REACT AND CANVAS API

clearEventHandler is registered to be called whenever the “clear” link isclicked. All we have to do is call clearCanvas and the canvas is cleared.releaseEventHandler is responsible for handling mouseup or touchendevents. These occur when the user stops holding the mouse button over thecanvas element. The event handler stores the state the user is no longerdrawing on the canvas and does a final redraw call. cancelEventHandler iscalled whenever the user moves his mouse or finger outside of the canvaselement. This handler method stops the processing of all future mouse eventsuntil the user performs another mousedown event on the canvas element.

Note the difference in syntax between these methods and the ones that werewritten earlier. This is because of the way Javascript (and thus Typescript)handle the binding of the this variable. Creating a closure for the eventhandlers allows for the handler to keep a correct reference to the instancewhen it’s run as an event handler. There’s a pretty good write-up availablehere.

Finally, we write the two methods responsible for handling the initialclicking or touch event and the moving of the cursor while in a down state,respectively:

private pressEventHandler = (e: MouseEvent | TouchEvent) => { let mouseX = (e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0].pageX : (e as MouseEvent).pageX; let mouseY = (e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0].pageY : (e as MouseEvent).pageY; mouseX -= this.canvas.offsetLeft; mouseY -= this.canvas.offsetTop; this.paint = true; this.addClick(mouseX, mouseY, false); this.redraw();}private dragEventHandler = (e: MouseEvent | TouchEvent) => { let mouseX = (e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0].pageX : (e as MouseEvent).pageX; let mouseY = (e as TouchEvent).changedTouches ? (e as TouchEvent).changedTouches[0].pageY : (e as MouseEvent).pageY; mouseX -= this.canvas.offsetLeft; mouseY -= this.canvas.offsetTop; if (this.paint) { this.addClick(mouseX, mouseY, true); this.redraw(); } e.preventDefault();}

The methods essentially do the same thing with a couple of minor differences:

(Video) Html5 Canvas Typescript - 1

  • get the X and Y coordinates of the event
  • transform the coordinates to be relative to the canvas element itself
  • add the click to the stored state
  • call redraw thereby updating the drawing surface

One difference is that dragEventHandler makes sure the paint variable istrue. This is to prevent cases where the user performed a click eventoutside of the canvas element but then moved the mouse inside of theelement. We also call preventDefault(reference)in dragEventHandler to improve the performance of the app. Without this,dragging the cursor can cause a degradation in responsiveness.

Note that both event handlers do a little bit of typepunning to work around the factthat the event handler is called for both mouse and touch events and thus thetype of e can vary. We detect the type of the event argument by checkingfor the presence of the changedTouches field; if it’s present, we have atouch event, otherwise it’s a mouse event.

Demo

You can see a live demo of this tutorial here.

Further reading

FAQs

What command is used to write the drawing to the canvas? ›

The print command is used to command the turtle to write something on the canvas.

Which JavaScript method is used to draw a circle on a canvas? ›

To draw arcs or circles, we use the arc() or arcTo() methods.

Is canvas HTML or JavaScript? ›

<canvas> is an HTML element which can be used to draw graphics via scripting (usually JavaScript).

Videos

1. Rendering an image to the Canvas in TypeScript
(Typescript Games)
2. TypeScript & HTML5 Canvas
(Johannes Diemke)
3. Using a Canvas to Create a Drawing App in Ionic - Part 1
(Joshua Morony)
4. Create a simple drawing app using javascript and HTML5 canvas
(JavaScript Academy)
5. Building a drawing app using Canvas & ReactJS | Manoj Singh Negi | Recraft Relic
(Recraft Relic)
6. Client-side Image Resizing with Canvas and TypeScript [Advanced Tutorial]
(Covalence)
Top Articles
Latest Posts
Article information

Author: Kieth Sipes

Last Updated: 03/10/2023

Views: 6344

Rating: 4.7 / 5 (47 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Kieth Sipes

Birthday: 2001-04-14

Address: Suite 492 62479 Champlin Loop, South Catrice, MS 57271

Phone: +9663362133320

Job: District Sales Analyst

Hobby: Digital arts, Dance, Ghost hunting, Worldbuilding, Kayaking, Table tennis, 3D printing

Introduction: My name is Kieth Sipes, I am a zany, rich, courageous, powerful, faithful, jolly, excited person who loves writing and wants to share my knowledge and understanding with you.