JSFiddle - React, Tailwind, and code Playground

by intrinsica

JavaScript

function getRandomColor() {
  return `hsl(${Math.floor(Math.random() * 255)}, 75%, 75%)`;
}

class Drawing {
  constructor({width = 500, height = 500, attachTo} = {}) {
    let canvas = document.createElement("canvas");
    let events = ["mousedown", "mousemove", "mouseup"];
    if ("ontouchstart" in window) {
      events = events.concat("touchstart", "touchmove", "touchend");
    }

    canvas.width = width;
    canvas.height = height;
    canvas.style.width = `${width / window.devicePixelRatio}px`;
    canvas.style.height = `${height / window.devicePixelRation}px`;
    canvas.style.backgroundColor = "black";

    
    events.forEach(evt => canvas.addEventListener(evt, this, false));
    
    this._canvas = canvas;
    this._ctx = canvas.getContext("2d");
    
    if (attachTo) {
      attachTo.appendChild(canvas);
    }
    
    this._drawing = false;
    this.changeColor();
  }
  
  handleEvent(evt) {
    let handler = `on${evt.type}`;
    if (typeof this[handler] === "function") {
      evt.preventDefault();
      return this[handler](evt);
    }
  }
  
  onmousedown(evt) {
    this.startDrawingAt({x: evt.clientX, y: evt.clientY});
  }
  
  ontouchstart(evt) {
    const touch = evt.targetTouches.item(0);
    if (touch) {
      this.startDrawingAt({x: touch.clientX, y: touch.clientY});
    }
  }
  
  onmousemove(evt) {
    this.continueDrawingTo({x: evt.clientX, y: evt.clientY});
  }

  ontouchmove(evt) {
    const touch = evt.targetTouches.item(0);
    if (touch) {
      this.continueDrawingTo({x: touch.clientX, y: touch.clientY});
    }
  }

  onmouseup(evt) {
    this.finishDrawing();
  }
  
  ontouchend(evt) {
    this.finishDrawing();
  }
  
  changeColor() {
    this._ctx.strokeStyle = getRandomColor();
  }
  
  startDrawingAt({x, y} = {}) {
    this._ctx.beginPath();
    this._ctx.moveTo(x * window.devicePixelRatio, y * window.devicePixelRatio);
    this._drawing = true;
  }
  
  continueDrawingTo({x, y} = {}) {
    if (this._drawing) {
     ...