Paint App

Simple canvas painting application

by Ben Gillbanks

HTML

<div class="canvas-wrapper">
    <canvas id="imageCanvas" width="400" height="400"></canvas>
    <canvas id="drawCanvas" width="400" height="400"></canvas>
</div>
<div class="tools">
    <button>Paint</button>
    <button>Fill</button>
</div>

CSS

body {
    margin: 0;
    padding: 0;
}

.canvas-wrapper {
    position: relative;
    border: 1px solid #000;
    height: 400px;
    width: 400px;
}
.canvas-wrapper canvas {
    position: absolute;
}
.canvas-wrapper #imageCanvas {
    pointer-events: none;
}

JavaScript

const config = {
  lineWidth: 5,
  lineCap: 'round',
  lineJoin: 'round',
  strokeColor: '#000',
};

const canvas = document.getElementById('drawCanvas');
const imageCanvas = document.getElementById('imageCanvas');
const context = canvas.getContext('2d');
const imageContext = imageCanvas.getContext('2d');
let painting = false;
let points = [];

const minDistance = 5;

function startPosition(e) {
  painting = true;
  points = [];
  draw(e);
}

function endPosition(e) {
	draw(e);	
    imageContext.drawImage( canvas, 0, 0 );
	clearCanvas();
    painting = false;
}

function calculateDistance(point1, point2) {
  const deltaX = point2.x - point1.x;
  const deltaY = point2.y - point1.y;
  return Math.sqrt(deltaX ** 2 + deltaY ** 2);
}

function draw(e) {

  if (!painting) return;

  const rect = canvas.getBoundingClientRect();
  const currentPoint = { x: e.clientX - rect.left, y: e.clientY - rect.top };
  
  //const currentPoint = { x: e.clientX - canvas.offsetLeft, y: e.clientY - canvas.offsetTop };

  if (points.length > 0 && calculateDistance(currentPoint, points[points.length - 1]) < minDistance) {
    return;
  }

clearCanvas();
  points.push(currentPoint);

  context.lineWidth = config.lineWidth;
  context.lineCap = config.lineCap;
  context.lineJoin = config.lineJoin;
  context.strokeStyle = config.strokeColor;

  context.beginPath();
  context.moveTo(points[0].x, points[0].y);
  
  if ( 1 === points.length ) {
  	context.lineTo(points[0].x, points[0].y);
  } else {
      for (let i = 1; i < points.length - 2; i++) {
        const c = (points[i].x + points[i + 1].x) / 2;
        const d = (points[i].y + points[i + 1].y) / 2;
        context.quadraticCurveTo(points[i].x, points[i].y, c, d);
      }

      context.quadraticCurveTo(
        points[points.length - 2].x,
        points[points.length - 2].y,
        points[points.length - 1].x,
        points[points.length - 1].y
      );
  
  }

  context.stroke();
  
}

function clearCanvas() {
 ...