joriszwart.nl

I code dreams™

Pythagoras theorem

Explanatorial Math Pythagoras

Interactive demo

Change the length of the sides to calculate the hypotenuse (the longest side of a right-angled triangle). Click anywhere in the image to do this. It is a bit clumsy, but you will manage 😃

Pythagoras

Source code

// FIXME temp hack for safari modules
const settings = {
  textColor: '#4b4b4b',
  primaryColor: '#ce5127',
  brandColor: '#e98a70',
  secondaryColor: '#27a2cc',
  tertiaryColor: '#86cfe4',
  backgroundColor: '#F9F4F2'
}


// setup 
const canvas = document.querySelector('canvas')
const context = canvas.getContext('2d')

const [width, height] = [canvas.width, canvas.height]
const gridSize = 50
const margin = 2 * gridSize

// lengths
let [a, b] = [5, 12]
let c = Math.sqrt(a * a + b * b)

// common style
context.font = '36px Helvetica'
context.textBaseline = 'middle'

context.fillStyle = settings ? settings.tertiaryColor : 'black'
context.lineWidth = 10
context.miterLimit = 1
context.strokeStyle = 'white'

const drawBackground = () => {
    context.save()

    // clear background
    context.fillRect(0, 0, width, height)

    // draw grid
    context.lineWidth = 2
    context.strokeStyle = settings ? settings.secondaryColor : 'black'
    context.beginPath()
    for (let x = gridSize; x < width; x += gridSize) {
        context.moveTo(x, 0)
        context.lineTo(x, height)
    }
    for (let y = gridSize; y < height; y += gridSize) {
        context.moveTo(0, y)
        context.lineTo(width, y)
    }
    context.stroke()

    // draw axes
    context.beginPath()
    context.lineWidth = 5
    context.strokeStyle = 'black'
    context.moveTo(2 * gridSize, 0)
    context.lineTo(2 * gridSize, height)
    context.moveTo(0, 6 * gridSize)
    context.lineTo(width, 6 * gridSize)
    context.stroke()

    context.restore()
}

const drawTriangle = () => {
    context.save()

    // y up
    context.scale(1, -1)
    context.translate(margin, margin - height)

    // draw triangle
    context.beginPath()
    context.moveTo(0, 0)
    context.lineTo(0, gridSize * a)
    context.lineTo(gridSize * b, 0)
    context.closePath()
    context.stroke()

    // right angle
    context.lineWidth = 5
    context.beginPath()
    context.moveTo(0, 25)
    context.lineTo(25, 25)
    context.lineTo(25, 0)
    context.stroke()

    context.restore()
}

const drawNumbers = () => {
    context.save()

    // FIXME magic number coordinates
    context.fillStyle = 'black'
    context.fillText(`a = ${a}`, 2.25 * gridSize, 4.5 * gridSize)
    context.fillText(`b = ${b}`, 6.25 * gridSize, 6.5 * gridSize)
    context.fillText(`c = √(a² + b²)`,       7.25 * gridSize, 1.5 * gridSize)
    context.fillText(`c = √(${a}² + ${b}²)`, 7.25 * gridSize, 2.5 * gridSize)
    context.fillText(`c = ≈${c.toFixed(2)}`, 7.25 * gridSize, 3.5 * gridSize)

    context.restore()
}

const update = () => {
    drawBackground()
    drawTriangle()
    drawNumbers()
}

const touch = e => {
    const rect = canvas.getBoundingClientRect()
    const [x, y] = [e.clientX - rect.left, e.clientY - rect.top]

    a = 6 - ~~(y / gridSize)
    b = ~~(x / gridSize) - 3
    c = Math.sqrt(a * a + b * b)

    update()
}

canvas.addEventListener('click', touch)
canvas.addEventListener('touch', touch)

update()