Simulate Gravity with jQuery

Visual effects on web pages are becoming more and more effective thanks to framework like jQuery. The idea of being able to adjust the look of a page with a click or a button gives the user a bit of extra interaction. This tutorials aims to give you insight of realistic gravity animations with jQuery.

View Demo
Download Source

The Overall Idea

The idea is simple: a block is floating in the air and holds another block with a string. If the user is to touch this string, it will break and the supported block will fall.

To get this idea working Javascript, we are going to use jQuery and a set of extra easing methods.

Getting Gtarted

Things you are going to need to in order to make this work are jQuery and a set of extra easing methods. The extra easing methods will help to create a natural effect if the rope snaps and the block falls.

To include jQuery, you can use the Google, api so you don’t have to upload jQuery yourself. That will save bandwidth and loading time, since the user might already have jQuery in their cache.

  • Upload the easing plugin to your web server in a folder where you’d like to.
  • Create an HTML file and include the scripts in the head section:
		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
		<script src="js/jquery.easing.1.3.js" type="text/javascript"></script>

Creating the HTML Layout

Time to make the HTML layout for the script to function on. Let’s review what we need to create:

  • The air where the blocks float.
  • Ground beneath the air.
  • Two blocks.
  • A rope of some kind which holds the blocks together.

The following HTML would match the description:

		<div id="air">
			<div class="block_container">
				<div class="block">
					Block 1
				</div>
				<div class='handle_wrap'>
					<div class="handle">
						&nbsp;
					</div>
				</div>
				<div class="block">
					Block 2
				</div>
			</div>
		</div>
		<div id="ground">
			&nbsp;
		</div>

Fairly easy right? The air doesn’t contain the ground, that would be silly. And the blocks are inside a container so they can fall down.

The handle_wrap is to prevent the block from going up when the rope snaps. Not only would it look weird, it’s also impossible in real life.

Giving the Page Some Style

To create a natural look, we are going to style each element using CSS. We’ll give the air a nice blue color and some room so the blocks can fall down a few feet. The blocks will be black and bold, to give them a nice heavy look. The rope will be red, like an elastic rope of some kind. The block container also needs to be styled to float in the air, giving it a funny look. The ground will obviously be a solid brown container.

The following CSS will do the trick:

		#air {
			height: 500px;
			background-color: #B4D7F4;
		}
 
		.block {
			width: 100px;
			padding: 20px;
			background-color: black;
			color: white;
			text-align: center;
		}
 
		.block_container {
			float: left;
			width: 140px;
			padding: 20px 0 0 100px;
		}
 
		.handle {
			width: 4px;
			height: 50px;
			background-color: red;
			cursor: pointer;
			margin: 0px auto;
		}
 
		.handle_wrap {
			height: 50px; /* use the same height as the handle itself */
		}
 
		#ground {
			padding: 20px;
			background-color: #5F3800;
		}

Note that the .handle and .handle_wrap have to be of same heights for it to work properly.

Writing the Javascript

I like to write my Javascript code as if I want to make adjustments to it later. To create a nice formatted script I declare functions and variables inside a variable. This variable will be called Gravity and will contain two functions (init and reset). This way, we can call the function in a semi Object Oriented way. Like: Gravity.init() and Gravity.reset().

When the document loads, you want to initialize the gravity, so we need to add a call to Gravity.init() when ready.

Create a quick instance of Gravity with two functions:

		var Gravity = {
 
			init: function() {
 
			},
 
			reset: function() {
 
			}
		}
 
		$(document).ready(function(){
			Gravity.init();
		});

Now you have a variable which is called Gravity and holds two empty functions. The document will also execute the init() function once the page is loaded.

In the next part of the Javascript, we are going to fill up the init function to create some functionality. And the functionality is to cut the rope once we hover over it with our cursor.

To do this, we need to think what kind of animation a rope would make. I’d say something like a bungee cord that snaps – which means our rope will be shorter in the end. We’ll change the height of the handle.

Add the following code inside the init function:

		$(".handle").mouseenter(function() {
 
			//animate the cutting of the rope
			$(this).animate({
				height: "20px"
			}, {
				duration: 1500,
				easing: "easeOutElastic"
			});
 
		});

Now every object in your webpage with the class handle will execute code once the object is entered with a cursor. In the function we let the rope animate so that it looks as if it’s cut loose.

Note how I put the easing option after the duration option. This easing option gives you the power of making the animation display differently.

But wait, the block isn’t falling yet. So we need to add that functionality to the same function!

There are three things you need to know in order to make the right animation:

  • Which block needs to fall?
  • What is the falling distance?
  • What creates a nice falling effect?

To know which element in the DOM needs to fall, we need to select the right element. In the function, we have an object called this. Logically thinking, the block would be the object below the rope. And to select that object, we need to know which is next in line. You can do this by looking for which object from the parent is next.

Select the block with the following code adding it to the mouseenter function:

		var block = $(this).parent().next();

Now onto the falling distance. This requires some math to figure out. The image below shows you what is needed to calculate the falling distance.

Basically it’s the block’s position from the top of the air container to the bottom minus the height of the block.

Add the following code to the mouseenter function to calculate the falling distance:

		var yposBlock = $(block).position()['top'] - $("#air").position()['top'];
		var fallDist = ($("#air").outerHeight() - yposBlock) - $(block).outerHeight();

So now we know how much the block needs to fall. So let’s make it fall!

		//let the block fall
		$(block).stop().animate({
			marginTop: fallDist+"px"
		}, {
			duration: 1000,
			easing: "easeOutBounce"
		});

Note how I added the easing to make the block bounce. We only need the bounce at the end so it is an easeOut.

We are now done with the mouseenter function, your block will fall to the ground as soon as you enter the rope with your cursor.

To make a button which resets the position of the block or brings it back, I made a sort of rewind function making everything snap back to the original position with the animations going in reverse.

		reset: function() {
			$(".handle").stop().animate({
				height: "50px"
			},{
				duration: 1000,
				easing: "easeInElastic"
			});
 
			$(".block").stop().animate({
				marginTop: "0px"
			},{
				duration: 1000,
				easing: "easeInBounce"
			});
		}

Conclusion

You can add more containers with blocks as shown on the demo page by adding the same code as in the block_container. This now gives you a funny thing to play around with and adjust to your likings.

I hope I have giving you a nice insight on how to create Javascript effects as they would appear in real life, easing and creating maintainable Javascript code. Obviously, this isn’t necessarily a real-world demo, but it should help you to gain a grasp on the fundamentals. Thanks for reading!



29

Comments