Last active
September 6, 2022 18:01
-
-
Save ferdaber/6da400effe91a904d824c2548ebf2a67 to your computer and use it in GitHub Desktop.
Animated Wedge Plotting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Animated Wedge Plotting |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Arc Plot</title> | |
</head> | |
<body> | |
<svg | |
id="svg" | |
viewBox="0 0 100 100" | |
width="500" | |
height="500" | |
xmlns="http://www.w3.org/2000/svg" | |
></svg> | |
<script type="text/javascript" src="main.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const svg = document.getElementById("svg"); | |
function rad(deg) { | |
return (deg * Math.PI) / 180; | |
} | |
function deg(rad) { | |
return (rad * 180) / Math.PI; | |
} | |
function polarToRect(angleDeg, radius, offset) { | |
const x = Math.cos(rad(angleDeg)) * radius + offset[0], | |
y = Math.sin(rad(angleDeg)) * -radius + offset[1]; | |
return [x, y]; | |
} | |
let pathId = 0; | |
function createArc(d0, d1, r, c, stroke = "black") { | |
const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); | |
path.id = `path-${pathId++}`; | |
path.setAttribute("strokeWidth", "1"); | |
path.setAttribute("stroke", stroke); | |
path.setAttribute("fill", "none"); | |
const [x0, y0] = polarToRect(d0, r, c), | |
[x1, y1] = polarToRect(d1, r, c); | |
const sweepBit = Number(d0 > d1); | |
path.setAttribute( | |
"d", | |
`M ${x0} ${y0} A ${r} ${r} 0 0 ${sweepBit} ${x1} ${y1}` | |
); | |
svg.appendChild(path); | |
} | |
function createWedge(d0, d1, r0, r1, c, fill = "black") { | |
const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); | |
path.id = `path-${pathId++}`; | |
path.setAttribute("stroke", "none"); | |
path.setAttribute("fill", fill); | |
const [x0, y0] = polarToRect(d0, r0, c), | |
[x1, y1] = polarToRect(d1, r0, c), | |
[x2, y2] = polarToRect(d1, r1, c), | |
[x3, y3] = polarToRect(d0, r1, c); | |
const sweepBit01 = Number(d0 > d1); | |
const sweepBit23 = 1 - sweepBit01; | |
path.setAttribute( | |
"d", | |
`M ${x0} ${y0} A ${r0} ${r0} 0 0 ${sweepBit01} ${x1} ${y1} L ${x2} ${y2} A ${r1} ${r1} 0 0 ${sweepBit23} ${x3} ${y3} Z` | |
); | |
svg.appendChild(path); | |
return path.id; | |
} | |
function updateWedge(pathId, d0, d1, r0, r1, c, fill = "black") { | |
const path = document.getElementById(pathId); | |
if (!path) { | |
throw new Error(`Cannot find path ID: ${pathId}`); | |
} | |
path.setAttribute("fill", fill); | |
const [x0, y0] = polarToRect(d0, r0, c), | |
[x1, y1] = polarToRect(d1, r0, c), | |
[x2, y2] = polarToRect(d1, r1, c), | |
[x3, y3] = polarToRect(d0, r1, c); | |
const sweepBit01 = Number(d0 > d1); | |
const sweepBit23 = 1 - sweepBit01; | |
path.setAttribute( | |
"d", | |
`M ${x0} ${y0} A ${r0} ${r0} 0 0 ${sweepBit01} ${x1} ${y1} L ${x2} ${y2} A ${r1} ${r1} 0 0 ${sweepBit23} ${x3} ${y3} Z` | |
); | |
return pathId; | |
} | |
const center = [50, 50]; | |
const radius = 45; | |
const NUM_FRAMES = 64; | |
const startAngles = [0, 24, 72, 144, 240].map((x) => x + 90); | |
const endAngles = [24, 72, 144, 240, 360].map((x) => x + 90); | |
const colors = ["red", "blue", "green", "yellow", "orange"]; | |
const START_ANGLE = startAngles[0]; | |
let frame = 0, | |
wedgeIds; | |
const rafCb = () => { | |
if (!wedgeIds) { | |
wedgeIds = startAngles.map((_, idx) => { | |
const startAngle = startAngles[idx], | |
endAngle = endAngles[idx], | |
color = colors[idx]; | |
const offsetStartAngle = | |
START_ANGLE + ((startAngle - START_ANGLE) * frame) / NUM_FRAMES; | |
const offsetEndAngle = | |
START_ANGLE + ((endAngle - START_ANGLE) * frame) / NUM_FRAMES; | |
return createWedge( | |
offsetStartAngle, | |
offsetEndAngle, | |
radius - 10, | |
radius, | |
center, | |
color | |
); | |
}); | |
} else { | |
startAngles.forEach((_, idx) => { | |
const wedgeId = wedgeIds[idx], | |
startAngle = startAngles[idx], | |
endAngle = endAngles[idx], | |
color = colors[idx]; | |
const offsetStartAngle = | |
START_ANGLE + ((startAngle - START_ANGLE) * frame) / NUM_FRAMES; | |
const offsetEndAngle = | |
START_ANGLE + ((endAngle - START_ANGLE) * frame) / NUM_FRAMES; | |
return updateWedge( | |
wedgeId, | |
offsetStartAngle, | |
offsetEndAngle, | |
radius - 10, | |
radius, | |
center, | |
color | |
); | |
}); | |
} | |
frame++; | |
if (frame > NUM_FRAMES) { | |
return; | |
} else { | |
window.requestAnimationFrame(rafCb); | |
} | |
}; | |
window.requestAnimationFrame(rafCb); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment