Skip to content

Instantly share code, notes, and snippets.

@dominikkaegi
Last active February 29, 2024 15:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save dominikkaegi/dd17bf0fc26ceb7170a6b917a8ce58c1 to your computer and use it in GitHub Desktop.
Save dominikkaegi/dd17bf0fc26ceb7170a6b917a8ce58c1 to your computer and use it in GitHub Desktop.

Canvas Introduction

1. Setting up Canvas and drawing first line

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  ctx.beginPath()
  ctx.moveTo(line.start.x, line.start.y)
  ctx.lineTo(line.end.x, line.end.y)
  ctx.lineWidth = line.lineWidth
  ctx.lineCap = line.lineCap
  ctx.strokeStyle = line.strokeStyle
  ctx.stroke()
}

const line = {
  start: {
    x: 100,
    y: 100
  },
  end: {
    x: 100,
    y: 200
  },
  lineWidth: 50,
  strokeStyle: 'blue',
  lineCap: 'round',
}

drawLine(ctx, line)

2. Deconstructing Objects with Default Values

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

const line = {
  start: {
    x: 100,
    y: 100
  },
  end: {
    x: 100, 
    y: 200
  },
  lineWidth: 50,
  strokeStyle: 'blue'
}

drawLine(ctx, line)

3. Drawing Points on mouse click

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

document.addEventListener('mousedown', function(e) {

  const position = {
    x: e.clientX - canvas.offsetLeft,
    y: e.clientY - canvas.offsetTop
  }

  const line = {
    start: position,
    end: position,
    lineWidth: 100
  }

  drawLine(ctx, line)
})

4. Drawing a line on mouse drag

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

let isPressed = false;
let mouseDownPos = null

document.addEventListener('mousedown', function(e) {
  isPressed = true
  mouseDownPos = {
    x: e.clientX - canvas.offsetLeft,
    y: e.clientY - canvas.offsetTop
  }

  const line = {
    start: mouseDownPos,
    end: mouseDownPos,
  }

  drawLine(ctx, line)
})

document.addEventListener('mouseup', function() {
  isPressed = false
})

document.addEventListener('mousemove', function(e) {
  if(isPressed) {
    let currentPos = {
      x: e.clientX - canvas.offsetLeft,
      y: e.clientY - canvas.offsetTop
    }

    let line = {
      start: mouseDownPos,
      end: currentPos
    }
    ctx.clearRect(0, 0, canvas.width, canvas.height)

    drawLine(ctx, line)
  }
})

5. Restructering Mouse Code

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

const mouse = {
  isPressed: false,
  down: null,
  current: null,
  up: null,
  setDown: function(event, element) {
    this.isPressed = true;
    this.down = this.getPosition(event, element)
  },
  setUp: function(event, element) {
    this.isPressed = false;
    this.up = this.getPosition(event, element)
  },
  setCurrent: function(event, element) {
    this.current = this.getPosition(event, element)
  },
  getPosition: function(event, element) {
    let position = {
      x: event.clientX - element.offsetLeft,
      y: event.clientY - element.offsetTop
    }
    return position
  }
}


function handleMouseDown(e) {
  mouse.setDown(e, canvas)

  const line = {
    start: mouse.down,
    end: mouse.down,
  }

  drawLine(ctx, line)
}
function handleMuseUp(e) {
  mouse.setUp(e, canvas)
}
function handleMouseMove(e) {
  if(mouse.isPressed) {
    mouse.setCurrent(e, canvas)

    let line = {
      start: mouse.down,
      end: mouse.current
    }
    ctx.clearRect(0, 0, canvas.width, canvas.height)

    drawLine(ctx, line)
  }
}

document.addEventListener('mousedown', handleMouseDown )
document.addEventListener('mouseup', handleMuseUp)
document.addEventListener('mousemove', handleMouseMove)

6. Drawing multiple lines

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

const mouse = {
  isPressed: false,
  down: null,
  current: null,
  up: null,
  setDown: function(event, element) {
    this.isPressed = true;
    this.down = this.getPosition(event, element)
  },
  setUp: function(event, element) {
    this.isPressed = false;
    this.up = this.getPosition(event, element)
  },
  setCurrent: function(event, element) {
    this.current = this.getPosition(event, element)
  },
  getPosition: function(event, element) {
    let position = {
      x: event.clientX - element.offsetLeft,
      y: event.clientY - element.offsetTop
    }
    return position
  }
}

function clearCanvas(ctx) {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
}

const lines = []

function draw() {
  clearCanvas(ctx)
  lines.forEach(function(line) {
    drawLine(ctx, line)
  })
}


function handleMouseDown(e) {
  mouse.setDown(e, canvas)

  const line = {
    start: mouse.down,
    end: mouse.down,
  }
  lines.push(line)
  draw()
}
function handleMuseUp(e) {
  mouse.setUp(e, canvas)
}
function handleMouseMove(e) {
  if(mouse.isPressed) {
    mouse.setCurrent(e, canvas)

    let line = {
      start: mouse.down,
      end: mouse.current
    }
    lines.pop()
    lines.push(line)
    draw();
  }
}

document.addEventListener('mousedown', handleMouseDown )
document.addEventListener('mouseup', handleMuseUp)
document.addEventListener('mousemove', handleMouseMove)

6. Drawing multiple lines

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

const mouse = {
  isPressed: false,
  down: null,
  current: null,
  up: null,
  setDown: function(event, element) {
    this.isPressed = true;
    this.down = this.getPosition(event, element)
  },
  setUp: function(event, element) {
    this.isPressed = false;
    this.up = this.getPosition(event, element)
  },
  setCurrent: function(event, element) {
    this.current = this.getPosition(event, element)
  },
  getPosition: function(event, element) {
    let position = {
      x: event.clientX - element.offsetLeft,
      y: event.clientY - element.offsetTop
    }
    return position
  }
}

const lines = []

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  lines.forEach(function(line) {
    drawLine(ctx, line)
  })
}

function handleMouseDown(e) {
  mouse.setDown(e, canvas)

  const line = {
    start: mouse.down,
    end: mouse.down,
  }
  lines.push(line)

  draw()
}
function handleMuseUp(e) {
  mouse.setUp(e, canvas)
}
function handleMouseMove(e) {
  if(mouse.isPressed) {
    mouse.setCurrent(e, canvas)

    let line = {
      start: mouse.down,
      end: mouse.current
    }
    lines.pop()
    lines.push(line)
    draw()
  }
}

document.addEventListener('mousedown', handleMouseDown )
document.addEventListener('mouseup', handleMuseUp)
document.addEventListener('mousemove', handleMouseMove)

7. Drawing with requestAnimationFrame

const canvas = document.querySelector('canvas')

canvas.width = window.innerWidth
canvas.height = window.innerHeight

const ctx = canvas.getContext('2d')

function drawLine(ctx, line) {
  const {
    start,
    end,
    lineWidth = 20,
    lineCap = 'round', 
    strokeStyle = 'white',
  } = line

  if(!start || !end) {
    throw new Error('Start or end of line not defined.')
  }

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.lineWidth = lineWidth
  ctx.lineCap = lineCap
  ctx.strokeStyle = strokeStyle
  ctx.stroke()
}

const mouse = {
  isPressed: false,
  down: null,
  current: null,
  up: null,
  setDown: function(event, element) {
    this.isPressed = true;
    this.down = this.getPosition(event, element)
  },
  setUp: function(event, element) {
    this.isPressed = false;
    this.up = this.getPosition(event, element)
  },
  setCurrent: function(event, element) {
    this.current = this.getPosition(event, element)
  },
  getPosition: function(event, element) {
    let position = {
      x: event.clientX - element.offsetLeft,
      y: event.clientY - element.offsetTop
    }
    return position
  }
}

const lines = []

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  lines.forEach(function(line) {
    drawLine(ctx, line)
  })
}

function handleMouseDown(e) {
  mouse.setDown(e, canvas)

  const line = {
    start: mouse.down,
    end: mouse.down,
  }
  lines.push(line)
}
function handleMouseUp(e) {
  mouse.setUp(e, canvas)
}
function handleMouseMove(e) {
  if(mouse.isPressed) {
    mouse.setCurrent(e, canvas)

    let line = {
      start: mouse.down,
      end: mouse.current
    }
    lines.pop()
    lines.push(line)
  }
}

document.addEventListener('mousedown', handleMouseDown )
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('mousemove', handleMouseMove)


window.requestAnimationFrame(function loop() {
  draw()
  window.requestAnimationFrame(loop)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment