(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(" "); } })();