Creating object in RaphaelJS - javascript

Is it possible to create Raphael's object but not drawing it on paper?
In example, i want to create circle, do some actions and show it on callback of actions.

You would need what is called an "offscreen canvas", something that is currently not implemented in html5 (some people talk about it).
Maybe you can create a canvas and set the css to display: none or visibility: hidden, and copy the image data from one canvas to the other.

You can use this construct:
var foo = circle(whatever).hide();
and then later use
foo.show();
inside whichever callback. it creates the circle object (you can see it in the dom) but you won't see it on the raphael paper

Related

raphaeljs default attributes

The default stroke for creating SVG elements with raphaeljs seems to be black 1px. I can manually turn it off every time I create an element, but I rather set it as a default attribute "stroke: none" to the entire paper. Is it possible?
I encountered this problem a little while ago; I believe this is a library default. Whilst you could change this in your library source, doing so would make updating library versions difficult, so you might be better off disabling it in the code that calls Raphael.
If you're worried about this being verbose, you could use a delegate function that hides the 'defaulting hacks' as you build similar shapes.
It depends if this is just for defaults, or trying to cut down repeated code etc. You could create your own shape with defaults you want as a possible alternative is what I was thinking...
var paper = Raphael('mydiv',400,400);
Raphael.fn.myBlueCircle = function (x,y,r) {
this.circle(x,y,r).attr({fill: "#00f", stroke: "none"});
};
paper.myBlueCircle(100,100,100);
paper.myBlueCircle(150,200,100);
jsfiddle
You may also want to do the same for sets if those are to be used with the new elements reference

css3 matrix3d value applied using jQuery not taking

I'm experimenting with rotating/animating an environment using CSS3 and javascript. So I have a cube object with faces, which lives inside a "rotator" object, which is the object that gets interacted with in the UI. I want to make it so that when you click a face, it appends it to a div outside of the rotator div, but applies the transformation matrices to the object from its parents, so that it appears with the same orientation on the outside of the "rotator" as it did inside, but can be animated and become independent of the rest of the objects in the "rotator" div.
Here is the function for the click event that should do this:
This depends on several custom functions, please see the fiddle for full code and reference to functions.
jQuery('#top').on('click',function(){
if(jQuery(this).parent().is('#cube')){ // only do this if it isn't already detached
M = jQuery(this).getTransMatrix(); // get the local transform of this
M = M.multiply(jQuery('#rotator').getTransMatrix()); // multiply it by the rotator's transform to get the final transform
jQuery(this).appendTo('#container'); // move this to the container div outside of the rotator
jQuery(this).css(CSS3.prefix+'transition','none'); // make sure that style changes, etc happen instantly
// wtf here
console.log(M.cssTransformString()); // just to check, we see the transform string before it is assigned. It's what it should be in my tests
jQuery(this).css(CSS3.prefix+'transform',M.cssTransformString()); // we apply the string. The wrong transformation results. If I double-check it from the console, it is NOT the string from the previous line
}
});
If you check out the fiddle, you will be able to drag around to rotate the cube. Clicking on the face will have some effect. The top face with the star is the one in question. When clicked, simply does not apply the transformation. Even if I log to console the transform string it's about to apply, the next operation does NOT result in that string being applied. It simply does not stick. HOWEVER, if I click and drag slightly, then release with the cursor still on the face, THEN the transform sticks. I have tried tracing virtually everything and I cannot figure out why the transform is only sticking if you click normally (without holding/moving at all)
Fiddle here:
http://jsfiddle.net/spaceboycoop/PWkB9/

HTML5 canvas Mouseover event

How do I bind a mouseover or any event for that matter to a drawn object on the canvas? For instance, I tried this:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
//STEP ONE
var stepOneRec = ctx.rect(20, 60, 266, 50);
ctx.stroke();
stepOneRec.addEventListener("mouseover", function() { alert('it works!'); });
On one site I looked at it showed a method using Kinetic.js. If that's the only way, I'll use it, I just assume that there's a way to bind events to drawn elements without extra plug-ins. Sorry Canvas noob. I made a fiddle with my code here: http://jsfiddle.net/jyBSZ/2/
(I started this as a posted comment, then realized it's an actual answer.)
Unfortunately, in javascript on it's own, you can't. There are no canvas objects, just the canvas as a whole, and whatever you drew on to its context. Plugins like kinetic can make objects for you, but the whole point of canvas is that the browser can think of it as a single static image.
If you want to, you can bind mousemove events to the canvas, track its position and the position where you drew stuff, and imply on your own that it's over "that object" (effectively what the plugins do), but it's all mousemove events on a single canvas rather than mouseover events on components of it. (You could even make your event binding simulate a mouseover event for the "objects", but underneath, it's still based on checking movement and checking your own object setup.)
The objects drawn within a canvas element are not HTML elements, just pixels, and therefore will not throw DOM events the way that HTML elements would.
You would need to track the locations of your objects yourself and handle the canvas' onmousemove event in order to determine when the mouse is over one of your drawn objects.
you can use jCanvas, take a look here
i made a jsfiddle example for your problem.
just modify next callbacks for desired result
function mouseOut(layer){
$("#mouse-over-text").html('none options selected');
}
function mouseIn(layer){
$("#mouse-over-text").html(getTextForId(layer.name));
}

How to copy a kineticjs stage to another canvas

I am writing an app where there may be hundreds of canvasses on a page. Rather than having the overhead of an individual stage for each canvas, I decided to have an editor that holds a stage. Once editing is completed it should copy the stage content to another canvas.
Stage offers toImage and toDataURL to get hold of the content however according this performance test, both those methods will be very slow compared to context.drawImage.
See: http://jsperf.com/copying-a-canvas-element
Since I only use one layer in a stage and a layer holds a canvas, I thought I could do this:
desticationCtx.drawImage(layer.getContext().canvas, 0,0);
unfortunately that doesn't produce any results (It does run though)
Since a stage has a bufferCanvas I also tried:
destinationCtx.drawImage(this.stage.bufferCanvas.element,0,0);
Again no results although I can see the content on the stage canvas on the page.
However if I dig down in my page to get to the actual canvas created and used by kineticjs:
destinationCtx.drawImage(document.getElementById('mydiv').children[0].children[0],0,0);
I do get results. What is the proper way to copy kineticjs stage content to another canvas?
access a layer canvas element like this:
var canvasElement = layer.getCanvas().getElement();
and the context like this:
var context = layer.getCanvas().getContext();
Here's the docs of interest:
http://kineticjs.com/docs/Kinetic.Layer.html#getCanvas
http://kineticjs.com/docs/Kinetic.Canvas.html
With the last and newer version of kineticjs the method from the as correct marked answer doesn't work anymore.
Nowadays I just used the following approach to get the kineticjs main canvas - with the help of jquery:
var canvas = $('#canvasDiv').find('canvas');
console.log("Canvas: %O", layerCanvas);
Just replace
#canvasDiv
with the ID of your container.

Tricky raphael svg animation

I've created a 'donut' chart originally from this jsfiddle, using raphael.
I have tweaked this script to suit my needs and currently have this being rendered.
My aim is to animate each slice (at the same time); for example make the blue slice grow to 60%; and the red slice shrink to 40%.
I have been able to redraw the slices by removing the existing one and quickly re-rendering a new one with adjusted values (e.g. 51, 49). But the problem here is that it is instant.
My question is,
(a) Can I animate this without the need to redraw the object (and how)?
(b) If not, how I can animate this effect using a redraw logic?
Yes. There is an example of doing this very thing on the Raphael demos page where you got the pie chart. See the Growing Pie demo.
You should separate the code in which you generate the path into a standalone function so you can use it later to return new paths. In order to use animate(), you'll need to define a function on the customAttributes object; it should return (at least) an object with the path property set to your slice's new path.
Since you have labels, you'll probably want to modify the code such that the pie slices expand/shrink relative to their center, so that you don't have to move the labels, too, since the labels are centered on their slice's "axis."
Update
Here's a JSFiddle with a simple example, pretty much the same as Dmitri's Growing Pie demo, except more like your chart. I export a setValue() method to change slice sizes and call it when the page loads. See his blog post about adding customAttributes, too.
In my last paragraph above, I was off the mark a bit. Your chart wasn't the one with labels; I had them mixed up. Also, it would be harder to keep slices centered, so I didn't do that after all. The animate() function sets each segment to its new starting and ending points on the circle, and Raphael figures out the intermediate points. As you can see, you can pass multiple arguments in an array.
this.customAttributes.slice = function(a0, a1) { /*...*/ }
// ...
chart.push(paper.path().attr({slice:[0, Math.PI/2 ]})
Can't see all the fiddle because I'm on iPod however it sounds like you need to have an animate call inside a function that you will need to write
Use the callback parameter that calls the function it sits inside.
Code your recursively called function so it eventually completes when all the work is done.
Each call to the function will happen at the end of every elapssed time interval you specify...

Categories

Resources