Animating a webpage with Box2d physics

Now this is what I call responsive design :-)

Now this is what I call responsive design!

You may have seen fun projects/demoes where a webpage is demolished using lifelike physics animations. Wario Land Shake It is a good example of that and it’s also allows the user to drag page elements around after the video is done playing. This however is created as a full page Flash, trying to look like a HTML page. Similar cases has also been done just by pre-rendering all into a video. So I wanted to have a go at doing this in HTML, as I haven’t seen that done before.

Continuing on what I learned creating my previous post about Box2d for JavaScript, I wanted to take it a step further replacing the debug renderer with elements from a webpage. The elements should be working as a blue print for the Box2d objects, and the transformation into the physics world should be transparent. I created a quick webpage using <div> elements with some mockup content and started on the steps to make it work:

  1. Scan the appropriate part of a webpage for <div> elements, creating the corresponding counterparts in the Box2d world. This turned out to be pretty straight forward, using a jQuery selector with the each() method looping through and creating boxes in Box2D. Positions and dimensions were extracted from CSS, being absolute positioned for the sake of simplicity. After they where reset to a 0,0 position, ready for letting the animation engine handle the positions later. A reference to the <div> was injected into the m_userdata of each of the Box2d bodies.
  2. Animating is done by looping through all fixtures within the bodies in the Box2d world, retrieving the position and rotation of the objects. Thus having rotation of the boxes, just using god ol’ top & left for positioning and animating had to be forfeit. Instead we use the transform property on CSS3, offsetting the position from 0,0 and setting the correct rotation. An added super bonus is setting transform: translateZ(0) in the parent element, we get super fast GPU accelerated animation. Using the -webkit vendor prefix, we even get pretty decent performance on iOS devices.
  3. Checking that all was in a 1:1 relationship between the browser rendering of the <div> elements and it’s Box2d counterparts also had to be done. I did this by using the debug renderer on a canvas, being displayed behind the elements. In the example you can turn it on and off, also making the <div> elements transparent to see both “worlds” at the same time.
  4. Handling both mouse and touch events is always a bit of a chore when you just want to focus at the task at hand. So I wrote my first Javascript tool ever, MouseAndTouch.js that handles both types of input in your typical “press-draw-up-end” manner. The code setup is probably not quite kosher, but writing it helped me along the way of learning JavaScript.

Ok, thats quite enough talk already. Go ahead and take it for a spin! Make sure that you drag the elements after they have been dropped :-) And please comment, esp. on my novice setup on the MouseAndTouch.js as a standalone tool.

For those of you that like more technical details, here are some things I found in the development process:

  • The rotate() method of CSS3 transform does not like negative values or infinite number of decimals. So you need to normalize the angle and fix the number of decimals. I ended up specifying the angle with degrees and setting the number of decimals to two.
  • Creating some shorthand methods for creating Box2d items helps speed up the development process.
  • Pingback: Recent tools and toys | CreativeJS()

  • Pingback: Running Box2D on server with Node.js via Socket.io | paal.org/blog()

  • Antoine BERNIER

    Hi,

    Just to mention, I did a similar experiment with Box2D logo: http://bl.ocks.org/3411189 (play with your mouse).

    Cheers

  • http://twitter.com/enzenhofer franz enzenhofer

    hi, very cool. one question, i would like to create a box2d4dom jquery plugin, what’s the license of your code if i may ask? can i reuse it, a liberal license MIT style would be just awesome.

  • honest

    hye … very cool work .. i need to know if we want to apply box2d on half page for instance like inside table | col1 | col2| col2 can you give your valueable suggestion to me Thanks

    • paalorg

      Thanx man, I’m not sure that I understand. I don’t use tables much. But of course, you could append box2d on any part of your page.

  • http://twitter.com/alexgrcs Alex Garces

    This is amazing. I was thinking a lot about the possibilities of moving DOM elements all around with Box2D. I think your code is really interesting. Good work!

    • paalorg

      Thanx :) It’s was fun to to as well!

  • http://www.facebook.com/profile.php?id=583997455 Noel Hunter

    Imagine one of the divs on the page has a webkit-transform rotate set before it is animated. How would you change createbox to account for the rotate, and start the box2d world with the correct x,y, and angle?

    I am trying to read the initial CSS rotation, and use that to set the box2d angle. I get it, convert it to radians, and set the angle on the bodydef. When I then step and set the css position and rotation with css again, the rotate value is correct– but the dom objects are offset to the right and up. I assume this has to do with the difference in width / height for rotated objects.

    Thanks for any advice.

    • paalorg

      Quite a while since I did this. But you will have to offset the rotation origin on the bodydef to the center of the object.

      PS. You should also enable the debug renderer to help sort things out

  • Lukasz Kowalski

    Oh my, i did my own implementation of this idea without even knowing someone else did this already, and i thought i was so innovative… And now when im lurking the internet for box2d related things im founding this site :) Anyway, here you can check this out, this is my newly started company site (company works from yesterday), something like portfolio etc. http://devbricks.com/ I did simply code there to be used with jQuery.

    • paalorg

      No wonder, It’s such a fun experiment. I was inspired by Wario Shake It on Youtube.

      I’m looking forward to the next time I play with Box2D. Tell me if you do some more experiments.

  • 30,000monkeys

    Awesome! This is exactly what I’ve been searching for. Is it OK for you if I use a modified version of your code in a non-commercial project?

    • paalorg

      Thanx. Sure, go ahead and play! :-)