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) {
...