Skip to content

Instantly share code, notes, and snippets.

@robbie01
Last active April 23, 2018 21:07
Show Gist options
  • Save robbie01/36ef012fc9e5bbc92e43e43e37b83098 to your computer and use it in GitHub Desktop.
Save robbie01/36ef012fc9e5bbc92e43e43e37b83098 to your computer and use it in GitHub Desktop.
kinda like lineart-svg
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Line Art</title>
</head>
<body>
<canvas id="c"></canvas><br>
<label for="r">Radius</label>
<input type="number" id="r" value="200"><br>
<label for="p">Points</label>
<input type="number" id="p" value="24"><br>
<button id="g">Go!</button>
<script src="lineart.js"></script>
</body>
</html>
var r = document.getElementById('r')
var p = document.getElementById('p')
var c = document.getElementById('c')
var g = document.getElementById('g')
const getPoints = (radius, npoints) => {
const points = [];
const theta = 2 * Math.PI / npoints;
for (let i = 0; i < npoints; ++i) {
const point = {};
point.x = radius + radius * Math.cos(theta * i);
point.y = radius + radius * Math.sin(theta * i);
points.push(point);
}
return points;
}
const createLine = (pointA, pointB) => {
return {
x1: pointA.x,
y1: pointA.y,
x: pointA.x,
y: pointA.y,
x2: pointB.x,
y2: pointB.y
};
};
const lerp = (v0, v1, t) => v0*(1-t)+v1*t
const lerpLine = (line, t) => {
line.x = lerp(line.x1, line.x2, t)
line.y = lerp(line.y1, line.y2, t)
}
const almostEqual = (numA, numB) =>
Math.abs(numA - numB) < Number.EPSILON;
const linesEqual = (lineA, lineB) =>
(almostEqual(lineA.x1, lineB.x1) &&
almostEqual(lineA.y1, lineB.y1) &&
almostEqual(lineA.x2, lineB.x2) &&
almostEqual(lineA.y2, lineB.y2)) ||
(almostEqual(lineA.x1, lineB.x2) &&
almostEqual(lineA.y1, lineB.y2) &&
almostEqual(lineA.x2, lineB.x1) &&
almostEqual(lineA.y2, lineB.y1));
const getLines = (radius, npoints) => {
const points = getPoints(radius, npoints);
const lines = [];
points.forEach(a => {
points.forEach(b => {
if (a !== b) {
const line = createLine(a, b);
if (!lines.find(l => linesEqual(line, l))) lines.push(line);
}
});
});
return lines;
};
function onGo() {
draw(parseInt(r.value), parseInt(p.value))
}
g.onclick = onGo
const frameCount = 60
let frames
let currentFrame
function draw(radius, points) {
c.width = c.height = radius * 2
var lines = getLines(radius, points)
var ctx = c.getContext('2d')
ctx.strokeStyle = '#000'
cancelAnimationFrame(currentFrame)
frames = -1
function drawFrame() {
ctx.clearRect(0, 0, 2*radius, 2*radius)
ctx.beginPath()
ctx.arc(radius, radius, radius, 0, Math.PI * 2)
ctx.stroke()
const t = (Math.cos((++frames / frameCount - 1) * Math.PI) + 1) / 2
lines.forEach(line => lerpLine(line, t))
ctx.beginPath()
lines.forEach(({ x1, y1, x, y }, i) => {
ctx.moveTo(x1, y1)
ctx.lineTo(x, y)
})
ctx.stroke()
if (frames < frameCount) currentFrame = requestAnimationFrame(drawFrame)
}
currentFrame = requestAnimationFrame(drawFrame)
}
onGo()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment