Skip to content

Drawing shapes and text

Drawing shapes and text

Canvas

Canvas graphics are drawn onto the <canvas> element, which can be given a width and a height in pixels.

There are two types of drawing: "2d" for two-dimensional graphics and "webgl" for three-dimensional graphics through the OpenGL interface. We will just look at "2d" graphics.

You can create a context object using the getContext method on the <canvas> DOM element. This object has methods with which you can draw on the <canvas>.

The coordinate system that canvas uses puts (0, 0) at the top-left corner with the positive y-axis going down from there, and the x-axis going up to the right.

A shape can be filled (its area is a certain colour) or stroked (a line is drawn on its edge).

Example:

js
let cx = document.querySelector("canvas").getContext("2d");
let patternImg = new Image();

// fetch.then

fetch("https://api.github.com/emojis")
.then(data => {
  return data.json();
})
.then(emojiData => {
  patternImg.src=emojiData.smiling_face_with_three_hearts;
  patternImg.onload=function(){
    let pattern = cx.createPattern(patternImg,'repeat');
    cx.strokeStyle = pattern;
    cx.lineWidth = 64;
    cx.beginPath();     // starts a new path
    for (let y = 32; y < 545; y += 128) {
      cx.moveTo(0, y);     // starts a new sub path at the point specified
      cx.lineTo(768, y);     // 
    }
    cx.stroke();
  }
});
let cx = document.querySelector("canvas").getContext("2d");
let patternImg = new Image();

// fetch.then

fetch("https://api.github.com/emojis")
.then(data => {
  return data.json();
})
.then(emojiData => {
  patternImg.src=emojiData.smiling_face_with_three_hearts;
  patternImg.onload=function(){
    let pattern = cx.createPattern(patternImg,'repeat');
    cx.strokeStyle = pattern;
    cx.lineWidth = 64;
    cx.beginPath();     // starts a new path
    for (let y = 32; y < 545; y += 128) {
      cx.moveTo(0, y);     // starts a new sub path at the point specified
      cx.lineTo(768, y);     // 
    }
    cx.stroke();
  }
});

Example:

js
let USpopulation = [];
let canvas = document.querySelector("canvas");
let cx = canvas.getContext("2d");

// fetch.then

fetch('http://api.worldbank.org/v2/countries/USA/indicators/SP.POP.TOTL?per_page=5000&format=json')
.then(data => {
  return data.json();
})
.then(jsonArr => {
    let myArray = jsonArr[1];
    for(let i=1960; i<2021; i++){
      USpopulation.push(myArray[i-1960]);
    }
    return USpopulation;
})
.then(drawRects => {
    for(let i=1960; i<2021; i++){
      let num = i-1960;
      let height = Math.round((USpopulation[num].value)/1000000);
      cx.fillStyle = "red";
      let x = 620-((num*10)+10);
      let y = (350-height)+10;
      let width = 5;
      cx.fillRect(x, y, width, height);
    }
});
let USpopulation = [];
let canvas = document.querySelector("canvas");
let cx = canvas.getContext("2d");

// fetch.then

fetch('http://api.worldbank.org/v2/countries/USA/indicators/SP.POP.TOTL?per_page=5000&format=json')
.then(data => {
  return data.json();
})
.then(jsonArr => {
    let myArray = jsonArr[1];
    for(let i=1960; i<2021; i++){
      USpopulation.push(myArray[i-1960]);
    }
    return USpopulation;
})
.then(drawRects => {
    for(let i=1960; i<2021; i++){
      let num = i-1960;
      let height = Math.round((USpopulation[num].value)/1000000);
      cx.fillStyle = "red";
      let x = 620-((num*10)+10);
      let y = (350-height)+10;
      let width = 5;
      cx.fillRect(x, y, width, height);
    }
});

Example:

js
let cx = document.querySelector("canvas").getContext("2d");     // creates a context object on the <canvas> element
let geoDataObj;


// fetch.then

fetch('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson')
.then(geoData => {
  // json() method of fetch API request object
  return geoData.json();     // returns a promise that parses JSON data and resolves/returns it as JavaScript Object
})
.then(geoDataObj => {
  let geoArray = geoDataObj.features;
  for (let i = 0; i < geoArray.length; i++){
    let magnitude = geoArray[i].properties.mag * 10;
    console.log(magnitude);
    let x = geoArray[i].geometry.coordinates[0];
    console.log(x);
    let y = geoArray[i].geometry.coordinates[1];
    console.log(y);
    let location = geoArray[i].properties.place;
    //cx.resetTransform();
    cx.translate(180, 90);
    cx.beginPath();     // method of Canvas 2D API starts a new path
    cx.arc(x, y, magnitude, 0, 2 * Math.PI);     // arc(x, y, radius, startAngle, endAngle)
    cx.strokeStyle = "red";
    cx.stroke();
    cx.font = "14px Arial";
    cx.fillStyle = "blue";
    cx.fillText(location, x, y+8);
  }
});
let cx = document.querySelector("canvas").getContext("2d");     // creates a context object on the <canvas> element
let geoDataObj;


// fetch.then

fetch('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson')
.then(geoData => {
  // json() method of fetch API request object
  return geoData.json();     // returns a promise that parses JSON data and resolves/returns it as JavaScript Object
})
.then(geoDataObj => {
  let geoArray = geoDataObj.features;
  for (let i = 0; i < geoArray.length; i++){
    let magnitude = geoArray[i].properties.mag * 10;
    console.log(magnitude);
    let x = geoArray[i].geometry.coordinates[0];
    console.log(x);
    let y = geoArray[i].geometry.coordinates[1];
    console.log(y);
    let location = geoArray[i].properties.place;
    //cx.resetTransform();
    cx.translate(180, 90);
    cx.beginPath();     // method of Canvas 2D API starts a new path
    cx.arc(x, y, magnitude, 0, 2 * Math.PI);     // arc(x, y, radius, startAngle, endAngle)
    cx.strokeStyle = "red";
    cx.stroke();
    cx.font = "14px Arial";
    cx.fillStyle = "blue";
    cx.fillText(location, x, y+8);
  }
});

Example:

js
let cx = document.querySelector("canvas").getContext("2d");
let worldMap = document.createElement("img");
worldMap.src = "images/worldMap.jpg";
worldMap.style.zIndex = 0;
let iSS = document.createElement("img");
iSS.src = "images/iss.png";
iSS.style.zIndex = 10;

// fetch.then

setInterval(function () {
  fetch('http://api.open-notify.org/iss-now.json')
  .then(issData => {
    return issData.json();
  })
  .then(issDataObj => {
    let longitudeX =  issDataObj.iss_position.longitude * 3.5;
    let latitudeY =  -(issDataObj.iss_position.latitude * 4.354);
    //console.log("long = " + longitudeX + " lat = " + latitudeY);
    cx.drawImage(worldMap, 0, 0, 1260, 790);
    cx.translate(924, 494);
    cx.drawImage(iSS, longitudeX - 50, latitudeY - 34, 100, 68);
    cx.resetTransform();
  })
}, 120);
let cx = document.querySelector("canvas").getContext("2d");
let worldMap = document.createElement("img");
worldMap.src = "images/worldMap.jpg";
worldMap.style.zIndex = 0;
let iSS = document.createElement("img");
iSS.src = "images/iss.png";
iSS.style.zIndex = 10;

// fetch.then

setInterval(function () {
  fetch('http://api.open-notify.org/iss-now.json')
  .then(issData => {
    return issData.json();
  })
  .then(issDataObj => {
    let longitudeX =  issDataObj.iss_position.longitude * 3.5;
    let latitudeY =  -(issDataObj.iss_position.latitude * 4.354);
    //console.log("long = " + longitudeX + " lat = " + latitudeY);
    cx.drawImage(worldMap, 0, 0, 1260, 790);
    cx.translate(924, 494);
    cx.drawImage(iSS, longitudeX - 50, latitudeY - 34, 100, 68);
    cx.resetTransform();
  })
}, 120);

A reference list (incomplete) of canvas methods and properties can be found here: https://www.w3schools.com/tags/ref_canvas.asp.

Mozilla's guide to canvas in the 2D context: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.

References

https://eloquentjavascript.net/17_canvas.html
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2Dhttps://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes
https://www.w3schools.com/tags/ref_canvas.asp

Content CC BY 4.0 | Code AGPL 3.0