A wave simulation using HTML5 Canvas. Click on it!
Last active
August 29, 2015 14:22
-
-
Save curran/9e035dcae9c8178ae649 to your computer and use it in GitHub Desktop.
Wave Simulation
This file contains 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
<html> | |
<head> | |
<title>1D Wave Simulation</title> | |
</head> | |
<body style="margin: 0px;"> | |
<canvas id="canvas"></canvas> | |
<script src="wave.js"></script> | |
</body> | |
</html> |
This file contains 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
var canvas = document.getElementById("canvas"); | |
var c = canvas.getContext("2d"); | |
var pullStrength = 0.01; | |
var dampeningFactor = 0.99; | |
var initialHeight = 0.5; | |
var cells = []; | |
var gridSize = 150; | |
var conservationOfMassCorrection = 0; | |
var cellWidth = 1 / (gridSize-1) * canvas.width; | |
var mouseX, mouseY, mouseDown; | |
var animate = true; | |
// Poor man's RAF polyfill | |
var nextFrame = requestAnimationFrame || setTimeout; | |
// This function executes once per animation frame | |
function executeFrame(){ | |
if(animate) | |
nextFrame(executeFrame); | |
clearCanvas(); | |
drawCells(); | |
iterateSimulation(); | |
executeMouseInteraction(); | |
} | |
// Initialize the water height | |
for(var i = 0; i < gridSize; i++){ | |
cells.push({ | |
// for a still initial surface | |
//height: 0.5, | |
// for an initial wave: | |
height: i === Math.floor(gridSize*1/4) ? 2 : initialHeight, | |
velocity: 0 | |
}); | |
} | |
function clearCanvas(){ | |
// resizes to full screen | |
canvas.width = window.innerWidth; | |
canvas.height = window.innerHeight; | |
cellWidth = 1 / (gridSize-1) * canvas.width; | |
} | |
function drawCells(){ | |
c.beginPath(); | |
c.moveTo(canvas.width, canvas.height); | |
c.lineTo(0, canvas.height); | |
for(var i = 0; i < gridSize; i++){ | |
var cell = cells[i]; | |
var x = i / (gridSize-1) * canvas.width; | |
var y = canvas.height - cell.height * canvas.height; | |
c.lineTo(x,y); | |
} | |
c.closePath(); | |
c.fill(); | |
} | |
// Increment the wave simulation: | |
// Neighboring cells pull on one another. | |
function iterateSimulation(){ | |
var avgHeight = 0; | |
for(var i = 0; i < gridSize; i++){ | |
// center cell | |
var c = cells[i]; | |
// left neighbor | |
var l = cells[((i - 1) + gridSize) % gridSize]; | |
// right neighbor | |
var r = cells[(i + 1) % gridSize]; | |
// pull toward neighbors | |
c.velocity += pullStrength * (l.height - c.height); | |
c.velocity += pullStrength * (r.height - c.height); | |
// increment velocity | |
c.height += c.velocity; | |
// ensure conservation of mass | |
c.height += conservationOfMassCorrection; | |
// apply dampening | |
c.velocity *= dampeningFactor; | |
avgHeight += c.height; | |
} | |
avgHeight /= (gridSize - 1); | |
conservationOfMassCorrection = initialHeight - avgHeight; | |
} | |
// Pull the wave cell closest to the mouse | |
function executeMouseInteraction(){ | |
if(mouseDown){ | |
for(var i = 0; i < gridSize; i++){ | |
var x = i / (gridSize-1) * canvas.width; | |
if(Math.abs(x - mouseX) < cellWidth){ | |
var cell = cells[i]; | |
cell.height = 1 - mouseY/canvas.height; | |
cell.velocity = 0; | |
} | |
} | |
} | |
} | |
// Record when the mouse is pressed | |
canvas.addEventListener("mousedown",function(e){ | |
mouseDown = true; | |
mouseX = e.clientX; | |
mouseY = e.clientY; | |
}); | |
// Record when the mouse is moved | |
canvas.addEventListener("mousemove",function(e){ | |
mouseX = e.clientX; | |
mouseY = e.clientY; | |
}); | |
// Record when the mouse is released | |
canvas.addEventListener("mouseup",function(e){ | |
mouseDown = false; | |
}); | |
// Draw the first frame | |
executeFrame(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment