Skip to content

Instantly share code, notes, and snippets.

@suspectpart
Last active April 4, 2020 17:39
Show Gist options
  • Save suspectpart/d5345fb213c8664091a5403e9e909921 to your computer and use it in GitHub Desktop.
Save suspectpart/d5345fb213c8664091a5403e9e909921 to your computer and use it in GitHub Desktop.
Draw
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Malen!</title>
<style>
body {
margin: 0;
overscroll-behavior: contain;
}
canvas {
position: absolute;
width: 100%;
height: calc(100% - 75px);
}
.tools {
position: sticky;
z-index: 10;
height: 75px;
background-color: bisque;
}
.brush {
cursor: pointer;
width: 50px;
height: 50px;
border-radius: 50%;
float: left;
margin-left: 20px;
margin-top: 10px;
}
.eraser {
cursor: pointer;
width: 60px;
float: right;
margin-right: 50px;
}
.selected {
border-style: outset;
border-color: white;
border-width: 5px;
margin-top: 5px;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
</style>
</head>
<body>
<div class="tools">
<div class="brush selected" data-color="black"></div>
<div class="brush" data-color="greenyellow"></div>
<div class="brush" data-color="hotpink"></div>
<div class="brush" data-color="white"></div>
<img class="eraser noselect" id="eraser" src="./sponge.png" alt="a sponge" />
</div>
<canvas id="canvas"></canvas>
<script>
// Javascript Framework "AngularMurkle"
HTMLElement.prototype.on = HTMLElement.prototype.addEventListener;
const $ = (id) => document.getElementById(id);
const $$ = (cls) => [ ... document.getElementsByClassName(cls) ];
const state = {};
((brushes, state) => {
const color = (brush) => brush.getAttribute("data-color");
const selected = (brush) => brush.classList.contains("selected");
const deselect = (brush) => brush.classList.remove("selected");
const select = (brush) => brush.classList.add("selected");
const pick = (brush) => {
brushes.forEach(deselect);
select(brush);
state.color = color(brush);
}
// initialize
select(brushes.find(selected));
// register events
for (let brush of brushes) {
brush.style.background = color(brush);
brush.on('click', ({target: brush}) => pick(brush));
}
})($$("brush"), state);
((canvas, state) => {
// initialize
const context = canvas.getContext("2d");
const nothing = (x, y) => {};
const rectangle = (x, y) => context.fillRect(x, y - canvas.offsetTop, 25, 25);
const circle = (x, y) => {
context.beginPath();
context.arc(x, y - canvas.offsetTop, 20, 0, 2 * Math.PI);
context.fill();
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
state.draw = nothing;
// register events
// Desktop
canvas.on("mousedown", ({ clientX: x, clientY: y }) => {
state.draw = circle;
context.fillStyle = state.color;
state.draw(x, y);
})
canvas.on("mousemove", ({ clientX: x, clientY: y }) => state.draw(x, y));
canvas.on("mouseup", () => state.draw = nothing);
canvas.on("mouseleave", () => state.draw = nothing);
// Mobile
canvas.on("touchstart", (event) => {
state.draw = circle;
context.fillStyle = state.color;
[ ...event.touches].forEach(({ clientX: x, clientY: y }) => state.draw(x, y));
});
canvas.on("touchmove", (event) =>{
[ ...event.touches].forEach(({ clientX: x, clientY: y }) => state.draw(x, y));
});
canvas.on("touchend", () => state.draw = nothing);
canvas.on("touchcancel", () => state.draw = nothing);
})($("canvas"), state);
((eraser, canvas) => {
// register events
eraser.on("click", () => {
canvas
.getContext("2d")
.clearRect(0, 0, canvas.width, canvas.height);
});
})($("eraser"), $("canvas"));
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment