JSFiddle - React, Tailwind, and code Playground
by Dogbert
HTML
<canvas id="canvas" width="300" height="300"></canvas>
<pre id="log"></pre>
<canvas id="playback" width="300" height="300"></canvas>
<p>
<button id="play">Play</button>
</p>
CSS
body {
text-align: center;
margin-top: 20px;
}
canvas,
#log {
border: 1px solid #333;
width: 300px;
height: 300px;
display: inline-block;
margin: 0;
padding: 0;
}
#log {
overflow: auto;
text-align: left;
background: white;
}
JavaScript
var el = document.getElementById('canvas');
var ctx = el.getContext('2d');
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
var isDrawing, points = [],
prevTime;
el.addEventListener('mousedown', function(e) {
isDrawing = true;
points = [{
x: e.offsetX,
y: e.offsetY,
delay: 0
}];
prevTime = +new Date;
updateLog();
});
el.addEventListener('mousemove', function(e) {
if (!isDrawing) return;
points.push({
x: e.offsetX,
y: e.offsetY,
delay: +new Date - prevTime
});
prevTime = +new Date;
updateLog();
draw(ctx, points);
});
el.addEventListener('mouseup', function() {
isDrawing = false;
});
var playback = document.getElementById("playback");
var playbackCtx = playback.getContext("2d");
playbackCtx.lineWidth = 5;
playbackCtx.lineJoin = 'round';
playbackCtx.lineCap = 'round';
document.getElementById("play").addEventListener("click", function() {
play(playbackCtx, points);
})
function updateLog() {
document.getElementById("log").innerText = JSON.stringify(points, null, 4);
}
function draw(context, points) {
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
var p1 = points[0];
var p2 = points[1];
context.beginPath();
context.moveTo(p1.x, p1.y);
for (var i = 1; i < points.length; i++) {
context.quadraticCurveTo(p1.x, p1.y, (p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
p1 = points[i];
p2 = points[i + 1];
}
context.lineTo(p1.x, p1.y);
context.stroke();
}
function play(context, points) {
tick(2);
function tick(i) {
if (i <= points.length) {
draw(context, points.slice(0, i));
setTimeout(function() {
tick(i + 1)
}, points[i].delay);
}
}
}