Imagine you are building a vehicle-system simulation or educational game and you want to show how transmission fluid behaves inside a transaxle (the combo transmission and differential unit often found in front-wheel-drive cars). You picture fluid swirling, churning, perhaps sloshing when the car accelerates or brakes.
Creating a transaxle fluid simulation in JavaScript is an advanced task that combines fluid dynamics with mechanical system modeling. It requires approximating complex physics with numerical methods. While commercial software like PreonLab uses the finite volume method for precise gearbox simulation, a realistic visual simulation can be built in JavaScript using the Navier-Stokes equations and rendering it to an HTML5 <canvas>.
Understand the Physical Scenario
What is a transaxle and why the fluid behaviour is interesting
A transaxle is a combined transmission and differential. Inside it you have gears spinning, fluid (transmission / gear oil) filling part of the housing, splashing as gears rotate, film forming on surfaces, heat being generated, etc. The fluid’s job is more than just lubrication it also assists in cooling, damping, and transmitting some torque (via the fluid film).
In our simulation we want to capture key visual/physical behaviours that make a transaxle fluid interesting:
- Gears rotating within a fluid bath → splash, swirling.
- Film formation on gear surfaces, recirculation of fluid pockets.
- Dependence of fluid behaviour on rpm, temperature, and gear load.
- Boundary interactions: fluid hitting housing walls, gears pulling fluid, vortex formation.
Simplifying all of that into a manageable simulation means choosing what to model (and what to approximate) carefully.
Which behaviours we will model
For our browser‐friendly JavaScript simulation we will model:
- A 2D ‘slice’ of the transaxle fluid chamber (so we can draw it to Canvas easily).
- A rotating gear (or two) inside a fluid area. The gear rotates at variable rpm via slider input.
- The fluid represented as particles (or discrete grid) that move under advection and diffusion and are influenced by the gear motion and boundaries.
- A simple film layer on gear teeth surfaces, approximated with a parameter for film thickness, which will affect drag/torque in the simulation.
- Temperature effect: a slider controlling fluid temperature, which adjusts viscosity and thus influences fluid velocity/drag.
We will approximate (not fully solve) complex Navier‐Stokes equations. That’s okay our goal is believable behaviour, not engineering precision. We’ll borrow ideas from generic fluid simulation tutorials (diffusion/advect/projection) but tailor them to our gear/fluid scenario.
Planning the Simulation in JavaScript
Canvas, dimensions, gear geometry
We’ll begin by setting up an HTML file with a <canvas> element. We pick a width/height, say 800×600 px.
In code:
<canvas id="simCanvas" width="800" height="600"></canvas>
In the JS we’ll get the canvas and its 2D context (ctx = canvas.getContext('2d')).
We’ll define a “chamber” rectangle (the fluid-filled space) and a gear drawn in the centre (for simplicity). The gear may be represented as a circle with teeth drawn or an image. We’ll rotate that gear at a certain rpm (converted to radians per second). The fluid particles or grid will respond.
Representing the Fluid Particles vs Grid
Generic fluid simulation tutorials often use a grid (dividing the simulation space into cells, each with velocity/density) and perform diffusion/advection, etc.
For our purpose, we could pick either:
- Particle system: Easier visually, each fluid “particle” moves around responding to forces (gear movement, boundaries). Good for splash and visual fun.
- Grid‐based solver: More accurate for fluid fields (velocity/density), but heavier and more complex.
I suggest a hybrid: For simplicity implement a particle system (say ~1000 particles) but apply “pseudo‐fluid” rules: particles are advected by a velocity field we compute from simple approximations (gear motion, drag, diffusion). Then we overlay simple grid‐based velocity smoothing to make behaviour smoother.
That way we get a friendly simulation that runs smoothly in browser, without heavy math.
Code Skeleton (JavaScript)
const canvas = document.getElementById('simCanvas');
const ctx = canvas.getContext('2d');
let particles = [];
const gear = { x: 400, y: 300, radius: 80, teeth: 20, angle: 0 };
let rpm = 1000; // initial rpm
let temperature = 80; // degrees C
const fluidFillHeight = 400;
function initParticles(count) {
for (let i=0; i<count; i++) {
particles.push({
x: Math.random() * canvas.width,
y: 300 + Math.random() * (fluidFillHeight - 300),
vx: 0, vy: 0
});
}
}
function updateGear(dt) {
const rps = rpm/60;
gear.angle += rps * 2*Math.PI * dt;
}
function computeFluidForces(p) {
// gear‐induced velocity: simple circular flow around gear
const dx = p.x - gear.x, dy = p.y - gear.y;
const dist = Math.sqrt(dx*dx + dy*dy);
if (dist < gear.radius*1.5) {
const tangVel = (rpm/60) * (gear.radius/ dist) * 0.05;
// compute tangential direction
const angle = Math.atan2(dy, dx) + Math.PI/2;
p.vx += Math.cos(angle) * tangVel;
p.vy += Math.sin(angle) * tangVel;
}
// viscosity/temperature drag
const viscosity = 1 + (100 - temperature)*0.02;
p.vx *= 1 - viscosity*0.001;
p.vy *= 1 - viscosity*0.001;
// diffusion (random small)
p.vx += (Math.random()-0.5)*0.02;
p.vy += (Math.random()-0.5)*0.02;
}
function updateParticles(dt) {
particles.forEach(p => {
computeFluidForces(p);
p.x += p.vx * dt*60;
p.y += p.vy * dt*60;
// handle wall boundaries
if (p.x < 0) { p.x=0; p.vx *= -0.3; }
if (p.x > canvas.width) { p.x=canvas.width; p.vx *= -0.3; }
if (p.y < 300) { p.y=300; p.vy *= -0.3; }
if (p.y > fluidFillHeight) { p.y=fluidFillHeight; p.vy *= -0.3; }
});
}
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw fluid region
ctx.fillStyle = '#eef';
ctx.fillRect(0,300,canvas.width,fluidFillHeight-300);
// draw gear
ctx.save();
ctx.translate(gear.x, gear.y);
ctx.rotate(gear.angle);
// gear body
ctx.fillStyle = '#888';
ctx.beginPath();
ctx.arc(0,0,gear.radius,0,2*Math.PI);
ctx.fill();
// teeth (simple)
for (let i=0;i<gear.teeth;i++) {
const a = i*(2*Math.PI/gear.teeth);
ctx.save();
ctx.rotate(a);
ctx.fillRect(gear.radius-10, -5, 20, 10);
ctx.restore();
}
ctx.restore();
// draw particles
ctx.fillStyle = 'rgba(0,120,200,0.6)';
particles.forEach(p => {
ctx.beginPath();
ctx.arc(p.x, p.y, 2,0,2*Math.PI);
ctx.fill();
});
}
let last = performance.now();
function animate(ts) {
const dt = (ts - last)/1000;
last = ts;
updateGear(dt);
updateParticles(dt);
draw();
requestAnimationFrame(animate);
}
initParticles(1000);
requestAnimationFrame(animate);
Deeper Features Making It Realistic and Interactive
Film thickness and gear splashing
In a real transaxle, fluid doesn’t just swirl freely: a thin film forms on rotating gear teeth surfaces, the gears partially splash fluid upward, and the housing may have a half‐fill fluid level. To approximate this, you can:
- Add a “film layer” parameter: say
filmThickness = someValue, which influences how many particles get “captured” near the gear surface. For example if a particle comes within e.g.gear.radius + filmThickness, reduce its speed (p.vx*=0.8) and slightly pull it around the gear surface for one or two rotations. - Add a “fill level” slider: so fluid height changes (simulate low fill vs full fill). At lower fluid levels you might see more splash and more gear surface exposed — you can modulate the tangential flow force accordingly (less fluid → more splash).
- Add “gear teeth mesh” effect: when rpm is high, you could trigger a brief “spray” of particles outward from gear teeth (emit new particles with radial velocity) to mimic splash.
Temperature and viscosity interplay
Transmission fluid viscosity decreases as temperature goes up. So:
- Temperature slider (say 20 °C to 120 °C).
- Map temperature → viscosity factor (e.g.,
viscosityFactor = baseViscosity * (120-temp)/100 + 1). Lower temperature → thicker fluid → slower particle movement, stronger drag, perhaps more film retention. - Use the viscosity factor in your drag computation (
p.vx *= (1 - dragCoeff*viscosityFactor)). - You can also change the colour of particles or fluid region based on temperature (blue for cold, red tint for hot) to give visual feedback.
Gear slip and torque feedback
To deepen the simulation you can show gear torque loading and slip:
- Let the user set “load” slider (low, medium, high). Under high load you have more drag from fluid film (since fluid carries torque). So you might increase drag proportionally, show gear slowed slightly, thicker film layer.
- Display on screen: “Gear RPM: XXX”, “Film thickness: YY mm”, “Torque drag: ZZ N·m”. These could be computed in simplified fashion: for instance
dragTorque = dragCoeff * filmThickness * rpmFactor.
This turns the simulation into a more educational experience rather than just visual.
Performance considerations for browser
Since we’re using JavaScript and running in typical browsers (including maybe mobile), performance matters:
- Keep particle count moderate (e.g., 500-2000).
- Use
requestAnimationFrameand measure delta time (dt) to keep simulation time‐consistent even if frame rate drops. - Avoid heavy math per particle: trigonometry is okay, but avoid solving large linear systems or heavy matrix operations.
- Consider capping maximum velocities to avoid runaway values.
- If you go for WebGL instead of canvas, you can leverage the GPU for many particles (but we’ll keep canvas/2D for simplicity).
- Offer a “quality” slider: reduce particle count or update frequency for slower devices.
Putting It All Together
Setup HTML and UI
Create index.html including canvas and UI sliders: rpm, temperature, fill level, load. Example:
<label>RPM: <input type="range" id="rpmSlider" min="100" max="5000" value="1000"></label>
<label>Temp (°C): <input type="range" id="tempSlider" min="20" max="120" value="80"></label>
<label>Fill level (%): <input type="range" id="fillSlider" min="30" max="100" value="80"></label>
<label>Load: <input type="range" id="loadSlider" min="0" max="100" value="50"></label>
<canvas id="simCanvas" width="800" height="600"></canvas>
Hook up event listeners in JavaScript to capture slider changes and update simulation parameters accordingly.
Initialize simulation state
In JS: define gear object, particles array, initial values, and read UI slider values into global variables (e.g., rpm, temperature, fillLevel, load).
Adjust fluid region height based on fillLevel: e.g. fluidFillHeight = 300 + (fillLevel/100)*200;.
Animation loop
As shown in the skeleton above: track lastTime, compute dt, update gear, update particles, draw.
Be sure to update UI (maybe show numeric readouts) and allow user to change sliders on the fly, adjusting simulation accordingly.
Particle update with scenario‐specific behaviour
In computeFluidForces(p): combine generic fluid advection/diffusion (inspired by standard fluid tutorials like Endre Simo’s) with scenario‐specific logic (gear‐induced tangential flow, film drag, temperature/viscosity). For example:
- If a particle is near gear surface: add tangential velocity vector away from gear centre.
- If fluid temperature is low (high viscosity): reduce particle speed, increase drag.
- If load is high: treat as thicker film → slower particles near gear → more energy dissipated (you could even reduce gear rpm over time to simulate drag).
This is new compared to many generic tutorials which only simulate free fluid; we’re simulating fluid because it’s inside a mechanical assembly.
Summary
We covered how to create a “transaxle fluid transmission fluid” simulation in JavaScript from understanding the physical scenario of a transaxle fluid bath, to planning a simulation with particles and gear interaction, to writing JavaScript code, to adding interactive UI and realistic behaviours like film thickness, temperature/viscosity interplay, gear splash, and performance tuning for browser deployment.

