rg/naloga_2/main.js
2024-11-17 19:09:01 +01:00

104 lines
2.2 KiB
JavaScript

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');
/** @type {number[][]} */
const points = [];
/**
* @param {number} x
* @param {number} y
*/
function addPoint(x, y) {
if (points.length === 0) {
points.push([x, y]);
return;
}
if (points.length === 1) {
const h1x = lerp(0.25, points[0][0], x);
const h1y = lerp(0.25, points[0][1], y);
const h2x = lerp(0.75, points[0][0], x);
const h2y = lerp(0.75, points[0][1], y);
points.push([h1x, h1y], [h2x, h2y], [x, y]);
return;
}
}
/**
* @param {number} t
* @param {number} a
* @param {number} b
* @returns {number}
*/
function lerp(t, a, b) {
return (1 - t) * a + t * b;
}
/**
* interpolates the points
* @param {number} t
* @param {number[]} p array of points
*/
function curve(t, p) {
if (p.length === 1) return p[0];
return lerp(t, curve(t, p.slice(0, -1)), curve(t, p.slice(1)));
}
function drawCircles() {
for (const [x, y] of points) {
context.beginPath();
context.ellipse(x, y, 10, 10, 0, 0, Math.PI * 2);
context.stroke();
}
}
function drawLines() {
for (let i = 0; i < points.length - 3; i += 3) {
const p1 = points[i];
const p2 = points[i + 1];
const p3 = points[i + 2];
const p4 = points[i + 3];
context.beginPath();
context.moveTo(p1[0], p1[1]);
context.lineTo(p2[0], p2[1]);
context.moveTo(p3[0], p3[1]);
context.lineTo(p4[0], p4[1]);
context.moveTo(p1[0], p1[1]);
for (let t = 0; t <= 1; t += 0.01) {
const x = curve(t, [p1[0], p2[0], p3[0], p4[0]]);
const y = curve(t, [p1[1], p2[1], p3[1], p4[1]]);
context.lineTo(x, y);
}
context.stroke();
}
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
if (points.length <= 0) return;
drawCircles();
drawLines();
}
function resizeCanvas() {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
draw();
}
window.addEventListener('mousedown', (e) => {
addPoint(e.pageX, e.pageY);
draw();
});
window.addEventListener('resize', resizeCanvas);
resizeCanvas();