74 lines
1.6 KiB
JavaScript
74 lines
1.6 KiB
JavaScript
(function () {
|
|
const svg = document.querySelector("svg");
|
|
const path = svg.querySelector("path");
|
|
const circles = toArray(svg.querySelectorAll("circle"));
|
|
let draggedCircle = null;
|
|
|
|
function update() {
|
|
const points = circles.map((circle) => ({
|
|
x: parseFloat(circle.getAttribute("cx")),
|
|
y: parseFloat(circle.getAttribute("cy")),
|
|
}));
|
|
|
|
path.setAttribute("d", toSvgPath(points));
|
|
|
|
const event = new CustomEvent("myPointsChanged", { detail: points });
|
|
document.dispatchEvent(event);
|
|
|
|
make_base();
|
|
}
|
|
|
|
/**
|
|
* Event handlers
|
|
*/
|
|
|
|
svg.addEventListener("mousedown", (event) => {
|
|
if (circles.includes(event.target)) {
|
|
draggedCircle = event.target;
|
|
}
|
|
});
|
|
|
|
document.addEventListener("mousemove", (event) => {
|
|
if (draggedCircle) {
|
|
const { height, left, top, width } = svg.getBoundingClientRect();
|
|
const x = clamp(event.clientX - left, 0, width);
|
|
const y = clamp(event.clientY - top, 0, height);
|
|
|
|
draggedCircle.setAttribute("cx", x);
|
|
draggedCircle.setAttribute("cy", y);
|
|
update();
|
|
}
|
|
});
|
|
|
|
document.addEventListener("mouseup", () => {
|
|
draggedCircle = null;
|
|
});
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
update();
|
|
});
|
|
|
|
/**
|
|
* Helpers
|
|
*/
|
|
|
|
function clamp(value, min, max) {
|
|
return Math.max(min, Math.min(value, max));
|
|
}
|
|
|
|
function toArray(value) {
|
|
return Array.prototype.slice.call(value);
|
|
}
|
|
|
|
function toSvgOperation(operation, { x, y }) {
|
|
return `${operation} ${x} ${y}`;
|
|
}
|
|
|
|
function toSvgPath(points) {
|
|
return [
|
|
toSvgOperation("M", points[points.length - 1]),
|
|
...points.map((point) => toSvgOperation("L", point)),
|
|
].join(" ");
|
|
}
|
|
})();
|