Matrix Transformations

Identity
Scale
Translate
Translate x Scale
Scale x Translate

The HTML file:

<html>
<head>
    <script src="demo.js" defer></script>
</head>
<body>
    <h1>Matrix Transformations</h1>
    <table>
        <tr><td>
             <canvas id="theCanvas" 
                     width=300 height=300 
                     style="border:1px solid black;">
             </canvas>
       </td>
       <td>
           <table>
              <tr>
                   <td>Identity</td><td><div id="idMatrix"></div></td>
              </tr>
              <tr>
                   <td style="color:red;">Scale</td>
                   <td><div id="scaleMatrix"></div></td>
              </tr>
              <tr>
                   <td style="color:green;">Translate</td>
                   <td><div id="translateMatrix"></div></td>
             </tr>
             <tr>
                  <td style="color:blue;">Translate x Scale</td>
                  <td><div id="tsMatrix"></div></td>
             </tr>
             <tr>
                   <td style="color:cyan;">Scale x Translate</td>
                   <td><div id="stMatrix"></div></td>
             </tr>
          </table>
       </td></tr>
</table>
</body>
</html>

demo.js

"use strict"

const canvas = document.getElementById("theCanvas")
const ctx = canvas.getContext('2d')

const SCALE = 3
const TRANSLATE = 75

function Transform(p, matrix) {
    let x = p.x * matrix[0][0] + p.y * matrix[0][1] + matrix[0][2]
    let y = p.x * matrix[1][0] + p.y * matrix[1][1] + matrix[1][2]
    let z = p.x * matrix[2][0] + p.y * matrix[2][1] + matrix[2][2]

    if (z != 1) {
       x /= z
       y /= z
    }
    return {x:x, y:y}
}

function DrawLine(p1, p2, matrix) {
    let a = Transform(p1, matrix)
    let b = Transform(p2, matrix)

    ctx.beginPath()
    ctx.moveTo(a.x, a.y)
    ctx.lineTo(b.x, b.y)

    ctx.stroke()
}

function Square(matrix) {
    let p1 = {x:10, y:10}
    let p2 = {x:10, y:20}
    let p3 = {x:20, y:20}
    let p4 = {x:20, y:10}

    DrawLine( p1, p2, matrix)
    DrawLine( p2, p3, matrix)
    DrawLine( p3, p4, matrix)
    DrawLine( p4, p1, matrix)
}

function Multiply(m1, m2) {
   let m3 = [[0, 0, 0],[0, 0, 0], [0, 0, 0]]

   
   for(let row = 0; row < 3; ++row) {
      for(let column = 0; column < 3; ++column) {
          for(let i = 0; i < 3; i++) {
              m3[row][column] += m1[row][i] * m2[i][column]
          }
      }
   }
   return m3
}

function PrintMatrix(label, m="") {
   let tableString = "<table border> "
   for(let row =0; row < 3; ++row){
      let rowString = "<tr>";
      for (let col = 0; col < 3; ++col) {
          rowString += "<td align=right>" + m[row][col] + "</td>"
      }
      rowString += "</tr>"
      tableString += rowString
   }
   tableString += "</table>"

   document.getElementById(label).innerHTML = tableString
}


// draw the initial box
ctx.strokeStyle = "black"
let identity = [[1,0,0],[0,1,0],[0,0,1]]
PrintMatrix("idMatrix", identity)
Square(identity)

//draw the scaled box
ctx.strokeStyle = "red"
let scale  = [[SCALE,0,0],[0,SCALE,0],[0,0,1]]
PrintMatrix("scaleMatrix", scale)
Square(scale)

//draw the translated box
ctx.strokeStyle = "green"
let translate  = [[1,0,TRANSLATE],[0,1,TRANSLATE],[0,0,1]]
PrintMatrix("translateMatrix" , translate)
Square(translate)

// draw translate then scale 
ctx.strokeStyle = "cyan"
let newMatrix = Multiply(scale, translate)
PrintMatrix("stMatrix", newMatrix)
Square(newMatrix)

// draw scale then Translate
newMatrix = Multiply(translate, scale)
PrintMatrix("tsMatrix", newMatrix)
ctx.strokeStyle = "blue"
Square(newMatrix)