Skip to content

Instantly share code, notes, and snippets.

@PM2Ring
Created July 26, 2021 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PM2Ring/25c503092bca5b4444a1112d2d1ca59b to your computer and use it in GitHub Desktop.
Save PM2Ring/25c503092bca5b4444a1112d2d1ca59b to your computer and use it in GitHub Desktop.
Basic Bezier curve, interactive
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SVG Bézier</title>
<style id="mystyle">
circle {
stroke: #222;
stroke-width: 0.5;
stroke-opacity: 0.25;
fill-opacity: 0.75;
}
.hull {
stroke: #555;
stroke-width: 0.5;
stroke-dasharray: 2 2;
fill: none;
}
.bezier {
stroke: #000;
stroke-width: 1;
fill: none;
}
</style>
</head>
<body>
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 200 200"/>
</body>
<script>
var svg = document.querySelector("svg"),
things = [],
dragData = {
target: null, ox: 0, oy: 0, x: 0, y: 0
};
function makeDot(x, y, r, color) {
const a = document.createElementNS(svg.namespaceURI, 'circle');
a.setAttribute("cx", x);
a.setAttribute("cy", y);
a.setAttribute("r", r);
a.setAttribute("fill", color);
svg.appendChild(a);
a.addEventListener("mousedown", onStart, false);
a.addEventListener("touchstart", onStart, false);
things.push(a);
}
function makePath(cls, codes) {
const a = document.createElementNS(svg.namespaceURI, 'path');
a.setAttribute("class", cls);
a.dataset.codes = codes;
updatePath(a);
svg.appendChild(a);
things.push(a);
}
function updatePath(p) {
const codes = p.dataset.codes;
let data = "";
for (let i=0; i<4; i++)
data += codes.charAt(i) + dotXY(things[i]) + " ";
p.setAttribute("d", data);
}
function dotXY(a) {
return a.cx.baseVal.value.toFixed(3) +
',' + a.cy.baseVal.value.toFixed(3);
}
function svgPointer(evt) {
const coords = evt.touches ? evt.touches[0] : evt;
const pt = new DOMPoint(coords.clientX, coords.clientY);
return pt.matrixTransform(evt.target.getScreenCTM().inverse());
}
function onStart(evt) {
if (dragData.target)
return;
const tgt = evt.target;
const isTouch = evt.type == "touchstart";
tgt.addEventListener(isTouch ? "touchmove" : "mousemove",
onMove, false);
tgt.addEventListener(isTouch ? "touchend" : "mouseup",
onEnd, false);
const pt = svgPointer(evt);
dragData.target = tgt;
dragData.ox = pt.x - tgt.cx.baseVal.value;
dragData.oy = pt.y - tgt.cy.baseVal.value;
}
function clamp(n, lo, hi) {
return Math.max(lo, Math.min(n, hi));
}
function onMove(evt) {
evt.preventDefault()
const pt = svgPointer(evt);
dragData.x = clamp(pt.x - dragData.ox, 0, 200);
dragData.y = clamp(pt.y - dragData.oy, 0, 200);
render();
}
function onEnd(evt) {
evt.target.removeEventListener(
evt.type == "touchend" ? "touchmove" : "mousemove",
onMove);
dragData.target = null;
}
function render() {
const tgt = dragData.target;
tgt.cx.baseVal.value = dragData.x;
tgt.cy.baseVal.value = dragData.y;
updatePath(things[4]);
updatePath(things[5]);
}
(function () {
const r = 12;
makeDot(20, 20, r, "#e55");
makeDot(180, 20, r, "#ea5");
makeDot(180, 180, r, "#5f5");
makeDot(20, 180, r, "#78f");
makePath("hull", "MLLL");
makePath("bezier", "MC");
})();
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment