
Here’s a self-contained HTML example that explains torque and lets you play with the values (force, lever arm, and angle) to see how torque changes. Just copy this into a file like torque.html
and open it in your browser.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Torque Demo – HTML + JS</title>
<style>
:root { --bg:#0f172a; --card:#111827; --ink:#e5e7eb; --muted:#9ca3af; --accent:#38bdf8; }
* { box-sizing: border-box; }
body {
margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Arial, sans-serif;
background: linear-gradient(180deg, var(--bg), #1f2937); color: var(--ink);
display: grid; place-items: center; min-height: 100vh; padding: 24px;
}
.wrap {
width: 100%; max-width: 980px; display: grid; gap: 20px;
}
.card {
background: var(--card); border: 1px solid #1f2937; border-radius: 16px; padding: 18px;
box-shadow: 0 10px 30px rgba(0,0,0,.25);
}
h1 { margin: 0 0 8px; font-size: clamp(22px, 3vw, 34px); }
p { color: var(--muted); margin: 8px 0 0; }
.grid {
display: grid; gap: 16px;
grid-template-columns: 1fr;
}
@media (min-width: 820px) { .grid { grid-template-columns: 1.1fr .9fr; } }
/* Controls */
.control { display: grid; gap: 8px; }
.control label { font-weight: 600; display: flex; justify-content: space-between; }
.control output { color: var(--accent); font-variant-numeric: tabular-nums; }
input[type="range"] { width: 100%; }
.row { display: grid; grid-template-columns: 1fr 90px; align-items: center; gap: 12px; }
.note { font-size: 14px; color: var(--muted); }
/* Result */
.result {
display: flex; align-items: baseline; gap: 10px; margin-top: 8px;
}
.result .big { font-size: clamp(28px, 5vw, 44px); font-weight: 800; color: var(--accent); }
.result .unit { color: var(--muted); font-weight: 600; }
/* Diagram */
.stage { background:#0b1220; border:1px solid #1f2937; border-radius:12px; padding:10px; }
svg { width: 100%; height: auto; display: block; }
.lever { stroke:#93c5fd; stroke-width:10; }
.pivot { fill:#f59e0b; }
.force { stroke:#f87171; stroke-width:6; marker-end:url(#arrow); }
.tick { stroke:#94a3b8; stroke-width:2; }
.text { fill:#cbd5e1; font-size:12px; }
.thetaArc { fill:none; stroke:#34d399; stroke-width:3; }
</style>
</head>
<body>
<div class="wrap">
<div class="card">
<h1>Torque (τ) Interactive</h1>
<p><strong>Torque</strong> measures the turning effect of a force about a pivot:
<em>τ = F × r × sin(θ)</em>, where <em>F</em> is force (N), <em>r</em> is lever arm (m),
and <em>θ</em> is the angle between the lever and the force direction.</p>
<div class="result">
<div class="big" id="tau">0.00</div>
<div class="unit">N·m</div>
</div>
<div class="note">Positive τ indicates counter-clockwise tendency in this diagram.</div>
</div>
<div class="grid">
<!-- Controls -->
<div class="card">
<div class="control">
<div class="row">
<label>Force F <span><output id="oF">50</output> N</span></label>
<input type="number" id="nF" min="0" max="500" step="1" value="50" />
</div>
<input type="range" id="rF" min="0" max="500" step="1" value="50"/>
<div class="row">
<label>Lever arm r <span><output id="oR">0.50</output> m</span></label>
<input type="number" id="nR" min="0" max="2" step="0.01" value="0.50" />
</div>
<input type="range" id="rR" min="0" max="2" step="0.01" value="0.50"/>
<div class="row">
<label>Angle θ <span><output id="oT">90</output> °</span></label>
<input type="number" id="nT" min="0" max="180" step="1" value="90" />
</div>
<input type="range" id="rT" min="0" max="180" step="1" value="90"/>
<p class="note">
Max torque at 90° (force ⟂ lever). Zero torque at 0° or 180° (force ∥ lever).
</p>
</div>
</div>
<!-- Diagram -->
<div class="card stage">
<svg viewBox="0 0 640 280" aria-labelledby="ttl desc" role="img">
<title id="ttl">Torque diagram</title>
<desc id="desc">Lever about a pivot at left, force arrow at the end, angle shown between lever and force.</desc>
<!-- defs -->
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#f87171"></path>
</marker>
</defs>
<!-- pivot -->
<circle class="pivot" cx="80" cy="140" r="10"></circle>
<text class="text" x="68" y="130">Pivot</text>
<!-- lever (updated via JS) -->
<line id="lever" class="lever" x1="80" y1="140" x2="380" y2="140" />
<!-- ticks every 50px -->
<g id="ticks"></g>
<!-- force arrow (updated via JS) -->
<line id="force" class="force" x1="380" y1="140" x2="380" y2="60" />
<!-- angle arc -->
<path id="theta" class="thetaArc" d="" />
<text id="thetaLabel" class="text" x="120" y="120">θ</text>
<!-- labels -->
<text class="text" x="280" y="160">Lever (r)</text>
<text class="text" x="390" y="90">Force (F)</text>
</svg>
</div>
</div>
<div class="card">
<h2>What you’re seeing</h2>
<ul>
<li><strong>Lever</strong>: blue bar from the pivot to the right — its length is <em>r</em>.</li>
<li><strong>Force</strong>: red arrow applied at the end. Angle to the lever is <em>θ</em>.</li>
<li><strong>Torque</strong>: computed as <code>τ = F × r × sin(θ)</code> and shown above.</li>
</ul>
<p class="note">Units: F in newtons (N), r in meters (m) → τ in newton-meters (N·m).</p>
</div>
</div>
<script>
// Elements
const rF = document.getElementById('rF'), nF = document.getElementById('nF'), oF = document.getElementById('oF');
const rR = document.getElementById('rR'), nR = document.getElementById('nR'), oR = document.getElementById('oR');
const rT = document.getElementById('rT'), nT = document.getElementById('nT'), oT = document.getElementById('oT');
const tauEl = document.getElementById('tau');
const lever = document.getElementById('lever');
const force = document.getElementById('force');
const thetaArc = document.getElementById('theta');
const thetaLabel = document.getElementById('thetaLabel');
const ticksGroup = document.getElementById('ticks');
// Sync helpers
function link(a, b, out, fmt=(v)=>v) {
const sync = (e) => { a.value = b.value = e.target.value; out.textContent = fmt(e.target.value); update(); };
a.addEventListener('input', sync);
b.addEventListener('input', sync);
}
// Formatters
const f2 = (v)=> Number(v).toFixed(2);
const f0 = (v)=> Number(v).toFixed(0);
// Init tick marks along lever reference (every 0.1 m assuming 100 px = 0.25 m below)
function drawTicks(pxLen){
ticksGroup.innerHTML = '';
// choose a step in pixels (every 50 px)
for(let x=130; x<=80+pxLen; x+=50){
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', x); line.setAttribute('y1', 130);
line.setAttribute('x2', x); line.setAttribute('y2', 150);
line.setAttribute('class','tick');
ticksGroup.appendChild(line);
}
}
function update() {
const F = parseFloat(rF.value);
const R = parseFloat(rR.value);
const T = parseFloat(rT.value) * Math.PI/180; // radians
oF.textContent = f0(F);
oR.textContent = f2(R);
oT.textContent = f0(rT.value);
// Torque
const tau = F * R * Math.sin(T);
tauEl.textContent = tau.toFixed(2);
// Map meters to pixels for the diagram (scale: 1 m ≈ 600 px * 0.5 = 300 px at r=2m → end x ≈ 80 + 300)
const pxPerMeter = 150; // simple scale
const endX = 80 + R * pxPerMeter;
const endY = 140;
// Update lever line
lever.setAttribute('x2', endX);
lever.setAttribute('y2', endY);
// Force arrow direction: angle relative to lever (lever is along +x). Draw at angle θ from vertical/down?
// We'll draw the force making angle θ with the lever: when θ=90°, arrow is upward.
const len = 80; // arrow length in px
const ang = (Math.PI/2) - T; // so θ=90° => ang=0 (pure up)
const fx = endX + len * Math.sin(ang);
const fy = endY - len * Math.cos(ang);
force.setAttribute('x1', endX);
force.setAttribute('y1', endY);
force.setAttribute('x2', fx);
force.setAttribute('y2', fy);
// Angle arc at pivot to indicate θ (draw small arc)
const arcR = 40;
const start = { x: 80, y: 140 - arcR }; // along +y negative (up)
const end = { x: 80 + arcR * Math.cos(0), y: 140 }; // placeholder
// We want arc between lever (+x) and force direction; draw arc centered at pivot
const a0 = 0; // lever along +x
const a1 = T; // angle θ from lever to force
const xStart = 80 + arcR * Math.cos(a0);
const yStart = 140 + arcR * Math.sin(a0);
const xEnd = 80 + arcR * Math.cos(a1);
const yEnd = 140 + arcR * Math.sin(a1);
const largeArc = (T % (2*Math.PI)) > Math.PI ? 1 : 0;
thetaArc.setAttribute('d', `M ${xStart} ${yStart} A ${arcR} ${arcR} 0 ${largeArc} 1 ${xEnd} ${yEnd}`);
thetaLabel.setAttribute('x', 80 + (arcR+12) * Math.cos(T/2));
thetaLabel.setAttribute('y', 140 + (arcR+12) * Math.sin(T/2));
drawTicks(endX-80);
}
// Link inputs
link(rF, nF, oF, f0);
link(rR, nR, oR, f2);
link(rT, nT, oT, f0);
// First render
update();
</script>
</body>
</html>
What this does
- Shows the torque formula τ = F × r × sin(θ).
- Lets you adjust Force (N), Lever arm (m), and Angle (°) with sliders/inputs.
- Displays the calculated torque in N·m and an SVG diagram that updates live (lever length, force direction, and angle arc).