Tip speed · Fixed-radius calculator
HTML for this example
Select the code and use your copy shortcut. Changes in this preview are temporary.
<!doctype html><html lang="en-US"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Tip speed · Fixed-radius calculator</title><style>*{box-sizing:border-box}body{margin:0;background:#f3f1eb;color:#202e35;font:16px/1.5 system-ui,sans-serif}main{max-width:1160px;margin:auto;padding:32px 28px 70px}h1{font-size:clamp(26px,4vw,42px);line-height:1.12;margin:8px 0 12px;letter-spacing:-.04em}h2{font-size:22px;margin:0 0 16px}h3{font-size:17px;margin:0 0 8px}p{margin:8px 0 16px}.eyebrow{text-transform:uppercase;letter-spacing:.15em;font-size:12px;font-weight:750;color:#45665e}.lede{color:#55636a;max-width:780px}.panel{background:#fff;border:1px solid #d9dfd9;border-radius:16px;padding:24px;margin:20px 0}.hero{background:#193f38;color:white}.hero .muted{color:#bfd6cb}.split{display:grid;grid-template-columns:1.1fr 1fr;gap:24px}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.row{display:flex;flex-wrap:wrap;gap:12px;align-items:center}.big{font-size:clamp(32px,5vw,58px);line-height:1.15;font-weight:750;letter-spacing:-.04em}.muted,small{color:#61716e}.badge{display:inline-block;padding:4px 9px;border-radius:20px;background:#e5efe8;color:#284e40;font-size:13px;font-weight:650}.warn{background:#fff2d2;color:#795213}.rule{border-top:1px solid #dce2dd;padding-top:16px;margin-top:16px}label{display:block;font-size:14px;font-weight:650;margin:12px 0 5px}input,select,textarea,button{font:inherit}input,select,textarea{width:100%;border:1px solid #aebbb5;border-radius:7px;background:white;color:#20332c;padding:10px;min-height:44px}textarea{min-height:96px;resize:vertical}button{min-height:44px;border:1px solid #80968c;border-radius:7px;padding:9px 14px;background:white;color:#1c4637;cursor:pointer}button.primary{background:#245d47;color:white;border-color:#245d47}button:disabled{opacity:.5;cursor:default}button[aria-pressed=true]{background:#d8eb90;color:#1c3d29;border-color:#536a2d}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:3px solid #d5782a;outline-offset:3px}.error{color:#913920;min-height:24px}pre,.record{white-space:pre-wrap;overflow-wrap:anywhere;font:14px/1.6 ui-monospace,monospace;background:#eef2ec;border-radius:8px;padding:16px}table{border-collapse:collapse;width:100%;font-size:14px}th,td{border-bottom:1px solid #dce2dd;text-align:left;padding:12px 8px;vertical-align:top}th{font-size:12px;text-transform:uppercase;letter-spacing:.06em}.scroll{overflow:auto}details{margin:24px 0}summary{cursor:pointer;min-height:44px;font-weight:650}svg{max-width:100%;height:auto}.small{font-size:13px}.stack>*+*{margin-top:12px}@media(max-width:720px){main{padding:22px 16px 48px}.split{grid-template-columns:1fr}.grid{grid-template-columns:repeat(2,minmax(0,1fr))}.panel{padding:18px;margin:16px 0}h1{font-size:32px}.desktop-table{min-width:680px}}@media(max-width:400px){.grid{grid-template-columns:1fr}main{padding:18px 14px}.panel{padding:16px}.row>button{flex:1}h1{font-size:29px}}</style></head><body><main><div class="eyebrow">Circular motion worksheet</div><h1>From rotation to rim speed</h1><p class="lede">Normalize the radius, convert revolutions per minute, and calculate speed at the rim.</p><section class="panel hero"><div class="eyebrow" style="color:#c1dcae" id="resultLabel">Rim speed</div><div class="big" id="result">3.141593 m/s</div><p class="muted" id="derive"></p></section><section class="split"><div class="panel"><h2>Known quantities</h2><label for="mode">Solve for</label><select id="mode"><option value="forward">Rim speed from RPM</option><option value="inverse">RPM from rim speed</option></select><div class="grid"><div><label for="kind">Size is a</label><select id="kind"><option value="">Choose</option><option value="radius">Radius</option><option value="diameter" selected>Diameter</option></select></div><div><label for="size">Size</label><input id="size" value="1" inputmode="decimal"></div><div><label for="unit">Size unit</label><select id="unit"><option value="">Choose</option><option value="m" selected>Meters (m)</option><option value="mm">Millimeters (mm)</option></select></div></div><label for="source" id="sourceLabel">Rotation rate (RPM)</label><input id="source" value="60" inputmode="decimal"><p class="small">Dot decimals, up to six decimal places; values ≤ 1,000,000. Size must be positive. Rate or speed may be zero.</p><div class="row"><button class="primary" id="calculate">Calculate</button><button id="reset">Reset fields</button></div><p class="error" role="status" id="error"></p></div><div class="panel"><h2>Keep radius and diameter distinct</h2><svg viewBox="0 0 320 220" role="img" aria-label="Original circle diagram: radius runs from center to rim; diameter crosses the whole circle and equals two radii."><circle cx="160" cy="110" r="85" fill="#edf2d8" stroke="#4c7054" stroke-width="2"/><path d="M75 110H245 M160 110L220 50" stroke="#b65a2e" stroke-width="3"/><circle cx="160" cy="110" r="4" fill="#244534"/><text x="193" y="68" font-size="18">r</text><text x="125" y="142" font-size="17">D = 2r</text></svg><p id="normal" class="record"></p></div></section><details open><summary>Worked record and rounding</summary><pre id="record"></pre><p>Displayed values are rounded to six decimal places. Calculations retain JavaScript double precision internally. π means the internal math constant; it is not accepted as typed numeric input. A displayed 3.141593 m/s is not exactly π m/s, so its inverse is approximately 60.000007 RPM. This is fixed-radius kinematic math, not a hardware rating or physical simulation. No record is saved after reload.</p></details></main><script>const $=id=>document.getElementById(id),put=(id,v)=>$(id).textContent=String(v),esc=s=>String(s).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
function number(raw,positive){if(!/^(?:[0-9]+)(?:[.][0-9]{1,6})?$/.test(String(raw)))throw Error('Use a nonnegative dot decimal with up to six decimal places.');const n=Number(raw);if(!Number.isFinite(n)||n>1e6||(positive&&n===0))throw Error(positive?'Size must be greater than zero and at most 1,000,000.':'Value must be at most 1,000,000.');return n}
function calculate(mode,kind,unit,size,source){if(!['forward','inverse'].includes(mode)||!['radius','diameter'].includes(kind)||!['m','mm'].includes(unit))throw Error('Choose a mode, size type and supported unit.');const r=number(size,true)/(unit==='mm'?1000:1)/(kind==='diameter'?2:1);return numeric(mode,r,number(source,false))}
function numeric(mode,r,v){if(!(r>0)||!Number.isFinite(r)||!(v>=0)||!Number.isFinite(v)||!['forward','inverse'].includes(mode))throw Error('Invalid calculation.');const rpm=mode==='forward'?v:60*v/(2*Math.PI*r),omega=2*Math.PI*rpm/60,speed=mode==='forward'?omega*r:v;return{r,rpm,omega,speed,result:mode==='forward'?speed:rpm}}
const fmt=n=>n===0?'0':n<.000001?'< 0.000001':n.toFixed(6);function clear(){put('result','—');put('derive','');put('normal','');put('record','');put('error','');put('resultLabel',$('mode').value==='inverse'?'Rotation rate':'Rim speed')}
function show(){clear();try{const mode=$('mode').value,r=calculate(mode,$('kind').value,$('unit').value,$('size').value,$('source').value);put('result',fmt(r.result)+(mode==='forward'?' m/s':' RPM'));put('normal','r = '+r.r+' m');put('derive','r = '+r.r+' m · ω ≈ '+fmt(r.omega)+' rad/s');put('record','Normalized radius: '+r.r.toPrecision(17)+' m'+String.fromCharCode(10)+'ω = 2π × RPM ÷ 60 = '+r.omega.toPrecision(17)+' rad/s'+String.fromCharCode(10)+(mode==='forward'?'v = ωr = '+r.speed.toPrecision(17)+' m/s':'RPM = 60v ÷ (2πr) = '+r.rpm.toPrecision(17)+' RPM'))}catch(e){put('error',e.message)}}
for(const id of ['size','source','kind','unit'])$(id).addEventListener(id==='size'||id==='source'?'input':'change',clear);function empty(){for(const id of ['size','source','kind','unit'])$(id).value='';put('sourceLabel',$('mode').value==='inverse'?'Rim speed (m/s)':'Rotation rate (RPM)');clear()}$('mode').addEventListener('change',empty);$('calculate').addEventListener('click',show);$('reset').addEventListener('click',()=>{$('mode').value='forward';empty();$('size').focus()});globalThis.Tool={calculate,numeric};show();</script></body></html>