A Box2D demo to show how to hook the physics engine up with SVG and the DOM.
The following code demonstrates how to 'hook-up' the SVG with box engine. An advantage of this approach is that SVG elements can revceive events (e.g. hover to change opacity).
import 'dart:html';
import 'dart:svg';
import 'dart:math';
import 'package:box2d/box2d.dart';
//hint: add the package to your dart editor project by opening the
//pubspec.yaml; adding Box2D under dependencies and then
//running pub install via the link that will be at the top right of page
...
World _world;
Map<String,TransformItem> _items = new Map<String,TransformItem>();
main {
...
//use css selector to create a collection of svg elements to animate
//(shapes defined in html doc as <path id="path_138" ... d="..."/> )
queryAll("[id^="path"]").forEach((SvgElement e){
//set the shape and position of the shape in the box2d world
var rect = e.getBoundingClientRect();
fixDef.shape = new CircleShape();
fixDef.shape.radius = 5.0/SCALE;
bodyDef.position.x = (rect.left+rect.width/2)/SCALE;
bodyDef.position.y = rect.top/SCALE;
//link the svg element to the fixture via the id attribute
bodyDef.userData = e.id;
//TransformItem is a helper class for operating on the SVG Element
//and is held in a Map for easy access, note the position is on
//SVG canvas not at world scale.
TransformItem item = new TransformItem(e);
item.center = new Vector(
(rect.left+rect.width/2).toDouble(),
(rect.top+rect.height/2).toDouble());
_items[e.id] = item;
//add the item to world
Body b = _world.createBody(bodyDef);
b.createFixture(fixDef);
item.orginalMass = b.mass; //playing with mass to add the jitter effect
//and add some user interaction
e.onMouseOver.listen((_)=> _.currentTarget.attributes["opacity"] = "0.2");
});
requestAnimationFrame().then(update);
}
...and the update method for each animation frame...
dynamic update(num highResTime){
_world.step(1/50,10,10);
_world.clearForces();
requestAnimationFrame().then(update); //keep the show running
//iterate through each box body
for(Body b = _world.bodyList; b != null; b = b.next){
if(b.type!=BodyType.STATIC){
//set up the relationship between body and point of attraction
Vector itemPosition = b.position;
Vector targetPosition = _targetPointOfAttraction;
Vector targetDistance = new Vector.zero();
targetDistance.addLocal(itemPosition);
targetDistance.subLocal(targetPosition);
num finalDistance = targetDistance.length;
targetDistance.negateLocal();
//divsors reduce the magnitude of force
targetDistance = new Vector(targetDistance.x/50,targetDistance.y/50);
//get the svg element's helper object
TransformItem path = _items[b.userData];
//playing around with mass
double multiplier = 1+1.1755*(_random.nextBool()?1:-1);
b.mass = _random.nextBool()? b.mass * multiplier: path.orginalMass;
//apply the attraction (comment this out for falling elements)
b.applyForce(targetDistance, b.position);
//translate the position of the svg Element
path.setTransform(
new Vector(b.position.x, b.position.y),
b.originTransform.rotation.toString());
//play around with opacity for effect
double opacity = double.parse(path.element.attributes["opacity"]);
path.element.attributes["opacity"] = "${opacity + 0.02 * (_random.nextBool()?-1:1)}";
}
}
}
Currently having problems running in IE (as at 2013-07-06).
View the full source code here and see the references below for tutrials on working with Box2D. For more info on the Dart Programming Language see dartlang.org.
Reference:
Our Google+ SVG-Developers community is brand new and looking for members. There is also a space here for your SVG links, examples and tutorials.