Path animation for image - raphael

I have to do some path based animation But the object which has to move over the path is IMAGE and NOT any rect/circle ...etc.
I am new to raphael.js and found no good documentation/demo regarding path animation for any external image.
For E.g.
var paper = Raphael(document.getElementById('pond'), 500, 256);
var fairyPath = paper.path('M70,75 q-85,50 100,0 q200,-140 -100,0');
var fairy = paper.image("assets/fairy.png", 0, 0, 30, 30);
fairy.animate({path: fairyPath}, 3000);
How can i related fairy with fairyPath and create animation?

Related

How to visualize PhysicsWorld / CollisionShape with debug renderer?

My test scene for Urho3D/Urhosharp contains two boxes (see screenshot).
For both, the red and the green box I added a RigidBody and a CollisionShape.
The shape for the red box is a sphere and for the blue one a box. I've enabled debug visualisation by adding:
app.Engine.SubscribeToPostRenderUpdate(args => {
app.Renderer.DrawDebugGeometry(false);
});
However, this does not render the collision shapes but only the wireframe of the objects (green lines).
Here's the code for the blue node:
var floorNode = app.RootNode.CreateChild("Floor");
floorNode.Position = Vector3.Zero;
floorNode.Scale = new Vector3(10, 1, 10);
var floorComp = floorNode.CreateComponent<Box>();
floorComp.SetMaterial(Material.FromColor(new Color(0, 0, 1, 0.5f)));
var rigidBody = floorNode.CreateComponent<RigidBody>();
rigidBody.Mass = 0;
var collNode = floorNode.CreateComponent<CollisionShape>();
collNode.SetBox(Vector3.One, Vector3.Zero, Quaternion.Identity);
And for the red one:
var boxNode = app.RootNode.CreateChild("Box");
boxNode.SetScale(2f);
var boxComp = boxNode.CreateComponent<Box>();
boxComp.Color = Color.Red;
boxComp.SetMaterial(Material.FromColor(Color.Red));
var rigidBody = boxNode.CreateComponent<RigidBody>();
rigidBody.Mass = 0f;
var collNode = boxNode.CreateComponent<CollisionShape>();
collNode.SetBox(Vector3.One, Vector3.Zero, Quaternion.Identity);
collNode.SetSphere(3f, Vector3.Zero, Quaternion.Identity);
The collision works but I'd love to see the physics world because it makes it easier to experiment.
And here's the solution: the default debug output of the Urho3D renderer does not include the physics components. It has to be added manually.
app.Engine.SubscribeToPostRenderUpdate(args => {
// Default debug rendering.
app.Renderer.DrawDebugGeometry(false);
// Use debug renderer to output physics world debug.
var debugRendererComp = app.Scene.GetComponent<DebugRenderer>();
var physicsComp = app.Scene.GetComponent<PhysicsWorld>();
if(physicsComp != null)
{
physicsComp.DrawDebugGeometry(debugRendererComp, false);
}
});
For this to work the scene must of course have a debug renderer and a physics component:
app.Scene.GetOrCreateComponent<PhysicsWorld>();
app.Scene.GetOrCreateComponent<DebugRenderer>();
Then the result is as expected. In the image below the red box has got a spherical collision shape:
The nice thing I noticed: since the collision shape is a child node of the actual node it will scale together with the node. This means if the box or sphere (or whatever) is created with a size of Vector3.One it will always match the actual node size.

Changing image on click Raphael paper

I have a program where the user can add images to a paper, using Raphael. Now I want to be able to change an image to another image when clicked. Is this possible? Do I have to add an ID to the images? If so, how?
var imgURL = "img/img.png";
var bankNoteImg = new Image();
bankNoteImg.src = imgURL;
var width = bankNoteImg.width;
var height = bankNoteImg.height;
var image = paper.image(imgURL, X, Y, width, height);
Use the click and attr function of Raphael api.
Element.click will take a function as a parameter. Use this to access the image element inside the function.
I created a simple demo
var paper = Raphael(document.getElementById("papercanvas"), 200, 200);
var img = paper.image(URL1, 100, 100, 100 , 100);
function changeImageSource() {
this.attr('src', URL2);
}
img.click(changeImageSource);

raphaeljs moving a 'container' set

I'm trying to understand how sets work with transforms. Basically, I would like to have a 'container' set with all children in it, that I can move around the canvas.
I created a fiddle to show what I mean, this is a simplification of a larger drawing. http://jsfiddle.net/thibs/Hsvpf/
I've created 3 squares, red, black, blue. Each are added to a set and then they are added to a main container (set). I've added outlines to show canvas and set.
Red and black sets do not have transforms on them, but blue does. Blue remains in the 'container' set... until the container gets a transform.
Why is that? I thought that transforms were applied to all the chidlren of the set...?
Thanks in advance
Here is the fiddle code:
var paper = Raphael('holder');
var container = paper.set();
paper.rect(0, 0, '100%', '100%').attr({
stroke : 'red'
});
var rectRedSet = paper.set();
var rectRed = paper.rect(100, 10, 20, 20).attr({
'fill' : 'red',
'stroke-opacity' : 0
});
rectRedSet.push(rectRed);
container.push(rectRedSet);
var rectBlackSet = paper.set();
var rectBlack = paper.rect(150, 10, 20, 20).attr({
'fill' : 'black',
'stroke-opacity' : 0
});
rectBlackSet.push(rectBlack);
container.push(rectBlackSet);
var rectBlueSet = paper.set();
rectBlue = paper.rect(0, 0, 20, 20).attr({
'fill' : 'blue',
'stroke-opacity' : 0
});
rectBlueSet.push(rectBlue);
rectBlueSet.transform('t50,150');
container.push(rectBlueSet);
var containerBBox = container.getBBox();
paper.rect(containerBBox.x, containerBBox.y, containerBBox.width, containerBBox.height).attr({
stroke : 'black'
});
//trying to get the entire container and its children to move to 0,0
//commenting out the transform below will keep rectBlue in the container...?
container.transform('t0,0');
A "set" in Raphael is not like a "group" in SVG. A set in Raphael is just a collection of elements that you can manipulate at the same time. So when you set the transform on the container set, it is really just setting the transform on every element inside the set, overwriting any previous transform settings.
You can append or prepend to existing transformations in Raphael using "..." notation.You need to change your last line to:
container.transform("...t0,0")
But "t0,0" doesn't actually move anything anywhere. If you want to move the container so the top left corner is at 0,0, then you need to write:
container.transform('...t-' + containerBBox.x + ',-' + containerBBox.y);

Most efficient way to get the DOM node associated with a Raphael paper element

Okay, this has made me feel a little peevish because it seems like it should be straightforward but... it's not?
I have a situation where I am layering several SVGs and divs over the top of each other using specific z-index attributes to control their rendering order. All of that works fine, but the only way I can discover to get the DOM node for a given paper element is as follows:
// given containerID, width, height, and zIndex are in scope
var canvas = Raphael( containerID, width, height );
var tempObject = canvas.rect( 0, 0, 1, 1, 0 ).attr( { fill: 'none', stroke: 'none' } );
var svgNode = tempObject.node.parentNode;
$(svgNode).css( { 'z-index': zIndex } );
This works, but it is patently inelegant. Anyone know how to get the paper's svg node directly?
canvas.canvas should do the trick.
To avoid naming confusion, you can do:
var paper = Raphael( containerID, width, height );
var svgNode = paper.canvas;

Making charts in RaphaelJS that are 100% width?

I have seen graphs in Flash & stuff that basically adapt nicely to whatever the size of the browser or flexible element they are inside of.... I'm not really too well versed with raphaelJS but can you do this, and if so, how?
In raphaeljs, you can call .setSize on a Raphael object to update its size. To adapt to runtime changes in browser window size, you can respond to a window resize event. Using jQuery, you could do:
// initialize Raphael object
var w = $(window).width(),
h = $(window).height();
var paper = Raphael($("#my_element").get(0), w,h);
$(window).resize(function(){
w = $(window).width();
h = $(window).height();
paper.setSize(w,h);
redraw_element(); // code to handle re-drawing, if necessary
});
This will get you a responsive SVG
var w = 500, h=500;
var paper = Raphael(w,h);
paper.setViewBox(0,0,w,h,true);
paper.setSize('100%', '100%');
Normally you could set the width to %100 and define a viewBox within SVG. But, Raphael JS manually set a width and height directly on your SVG elements, which kills this technique.
Bosh's answer is great, but it was distorting the aspect ratio for me. Had to tweak a few things to get it working correctly. Also, included some logic to maintain a maximum size.
// Variables
var width;
var height;
var maxWidth = 940;
var maxHeight = 600;
var widthPer;
function setSize() {
// Setup width
width = window.innerWidth;
if (width > maxWidth) width = maxWidth;
// Setup height
widthPer = width / maxWidth;
height = widthPer * maxHeight;
}
var paper = Raphael(document.getElementById("infographic"), 940, 600);
paper.setViewBox(0, 0, 940, 600, true);
window.onresize = function(event) {
setSize();
paper.setSize(width,height);
redraw_element();
}