Raphael.js function getBBox give back NAN/NAN/NAN in IE8 - javascript

using Raphaƫl 2.1.4 - JavaScript Vector Library
do something like that:
var textDummy = paper.text(50,500, 'hello world').attr({fill: 'transparent', 'font-size': 14});
var textBox = textDummy.getBBox();
with chrome and firefox everything is fine,
but in IE8 it give back NaN/NaN/NaN,
par exemple textBox.height is NaN.
how i can fix this?

i found a workaround solution from this answer to the question
"Raphael JS and Text positioning"
If i use _getBBox() instead of getBBox() everything is working in ie 8 also.
_getBBox() is undocumented but used internally by Raphael itself, and it works!

I had the same problem in Rapahel 2.2.0 and 2.2.1, and using ._getBBox() didn't fix it for me.
What did fix it for me is falling back to .auxGetBBox() if it's defined and regular .getBBox() doesn't work, like this:
var bbox = path.getBBox( );
// Workaround for apparent bug in Raphael's VML module's getBBox() override
if( isNaN( bbox.x ) && path.auxGetBBox ){
bbox = path.auxGetBBox();
}
I don't have a fix for the underlying bug, but I have found the source of it.
In VML mode, Raphael takes the initial getBBox() function, saves it as auxGetBBox() on the element prototype, then replaces it with a function that appears to be broken.
It has calculations based on a variable defined as var z = 1/this.paper._viewBoxShift.scale;, which clearly expects _viewBoxShift.scale to be some factor of the scale of the current viewbox compared to the initial viewbox , but actually _viewBoxShift.scale is an object like this which appears to come from paperproto.getSize():
{ height: someNumber, width: someNumber }
This is where all the NaNs are coming from. Cannae divide by an object.
So this workaround works fine if no zoom is applied using a viewbox, but may give incorrect results if a zoom has been applied (something I can't get to work at all in recent versions of raphael in VML mode, but that's a seperate question). Fixing that will involve digging deep into Raphael's VML module to pipe a proper zoom factor into this z variable.

Related

create animations from Javascript using embedded SVG in XHTML

I use embedded SVG in XHTML and want to create animations from Javascript, but it does not work as expected
I am modeling business processes with XPDL and connect the simulation to a SVG graphics which I animate using javascript. I am doing this in Firefox, and model and graphics are embedded in XHTML. Now the problem is that I want to use an animateMotion-Tag to move an object along a path. Both are already existing, so I tried writing my solution into the SVG file, and this worked fine. It looked like:
<animateMotion xlink:href="#id1" rotate="auto" dur="2s">
<mpath xlink:href="#id2">
</animateMotion>
Of course, the namespaces are set correctly, so this works as expected. I trigger it manually, so there is no begin time needed. Now, my approach for doing the same thing in an existing mixed XHTML/SVG-dom:
function moveAlongPath(elemId,pathId,rotate,duration)
{
var svgNs = "http://www.w3.org/2000/svg";
var xlinkNs = "http://www.w3.org/1999/xlink";
var motionElem = document.createElementNS(svgNs,"animateMotion");
motionElem.setAttributeNS(xlinkNs,"href","#" + elemId);
motionElem.setAttributeNS(svgNs,"rotate",rotate);
motionElem.setAttributeNS(svgNs,"dur",duration + "ms");
var pathRef = document.createElementNS(svgNs,"mpath");
pathRef.setAttributeNS(xlinkNs,"href","#" + pathId);
motionElem.appendChild(pathRef);
var animElem = svgRootNode.getElementById(elemId); // It is indeed the <svg>-Node
animElem.appendChild(motionElem);
// Setting x and y to 0 is important for the Element to be "on" the Path
animElem.setAttribute("x",0);
animElem.setAttribute("y",0);
motionElem.beginElement();
}
When I check the dom in firebug, this seems to produce the same node structure with the same attributes, although the href isnt prefixed with xlink:, but setAttributeNS should do this, right? The problem here is that i cannot start the animation with beginElement(). Nothing happens here.
I hope there is help out there, i am really desperate right now.
EDIT:
I found it at last. The problem disappears when I use
setAttributeNS(null,"attr",value)
instead of
setAttributeNS(svgNs,"attr",value)
Correct this if I am wrong, but is not my first approach the way XML was thought? That there shouldn't be namespaceless attributes? Anyway - SOLVED!
Use
setAttributeNS(null,"attr",value)
instead of
setAttributeNS(svgNs,"attr",value)
variableElementNS.href.baseVal = value;

apply all transform matrices

I am looking for a possibly fast way to apply all transform matrices of a given svg-graphic. In other words: the algorithm should remove all "transform" attributes and transform all coordinates of the graphic to absolute coordinates.
Is their any library that can do this, or is their any SVGDomInterface method that coulld do that?
EDIT::
If I call the consolidate method like this:
$.each( svg.find( 'path' ), function( i ){
this.transform.baseVal.consolidate();
});
nothing happens, if i call it like this:
$.each( svg.find( 'path' ), function( i ){
this.transform.animVal.consolidate();
});
i get this error:
So, how should i use the "consolidate" method, on which elements shall I call it?
Greetings
philipp
Here's a jsFiddle with some javascript library code (based in part on Raphael.js) to bake the transforms into all paths' data:
http://jsfiddle.net/ecmanaut/2Wez8/
(Not sure what's up with Opera here, though; it's usually best in class on SVG. I may be stumbling in some way the other browsers are more forgiving about.)
The consolidate method only reduces the list of matrices to a single matrix. And the error you get on the animVal example is because you are not allowed to modify the animated values (consolidate destructively modifies the transform list).
To answer your question, no there's no existing method in SVG DOM that applies the transforms by modifying the values of paths etc. There are options in Inkscape (and Illustrator too IIRC) for applying transforms like that.
If you're looking for a library or utility that does this you can try SVG Cleaner.
SVG Cleaner didn't seem to apply all transforms for me, but Inkscape does. Here's the command line I use when I need to apply one:
inkscape copy-of-file.svg --select=id-of-node \
--verb=EditCut --verb=EditPaste \
--verb=FileSave --verb=FileClose
Assuming you have "Transforms -> Store transformation" set to "Optimized" in inkscape's prefs (I believe it is on by default), this will apply it and produce the wanted result. Be sure you operate on a copy of your input file, as the operation replaces your original file!
If you are running this on a mac, you may want to first do this in your shell:
alias inkscape=/Applications/Inkscape.app/Contents/Resources/bin/inkscape
Better use EditPasteInPlace instead of EditPaste. EditPaste pastes at the mouse location, which is not the location of the node.
In order to retreive the path relative to some other, parent DOM node (e.g. the SVG root container), you can use the technique here.
It uses SVG.getTransformToElement which calculates the transform between a parent and some node on the SVG tree. The returned object contains methods to return the inverse of the transform, etc, to do practical things with it.
How to determine size of Raphael object after scaling & rotating it?
I dont know exactly what you are trying to achieve, but this has the power to do it.

Why doesn't createRadialGradient work on Firefox?

I'm working with the canvas tag of HTML5 and JavaScript to access the canvas methods and properties.
This code works on Chrome but it doesn't work on Firefox: http://jsfiddle.net/thirtydot/BD3xA/.
Does anyone know why?
createRadialGradient works on Firefox, but addColorStop does not work completely - and will throw an exception if you pass in a transparency along with your color.
For example, after you create a radial gradient:
var grad = ctx.createRadialGradient(centerX,centerY,outRadius,centerX,centerY,outRadius+pad);
var colorOut="rgba(100,200,100,0.7)";
grad.addColorStop(0,'rgba(0,0,0,0)');
grad.addColorStop(0.01,colorOut);
The above works great on chrome, but will not work on FF because of the 0.7 in the rgba color.
So, I use something like:
colorOut= ($.browser.mozilla)?'#D88':'rgba(200,100,100,0.7);';
This doesn't make gradients look quite so nice on FF, but functions.
Of course, you should cache that $.browser.mozilla earlier - make a var IS_MOZILLA = $.browser.mozilla; and then just use that (so that you minimize class calls... as saving every computation in complex drawing calls is important).

Draw Polygon with GPolygon without GMap

Anyone know how I can draw Polygons with GPolygon from Google Map without having a map, inside other elements? Or anyone know any framework to do it with the same features like GPolygon?
I would like to have this "draw polygon" on a custom element, like div:
<div id="MyArea"></div>
Check out Raphael, a javascript library that wraps around VML in IE and SVG in standards compliant browsers. It's fairly easy to use and quite well documented.
Granted, the path element (used to draw polygon and polylines) uses the SVG path string syntax which is a bit cryptic but quite easy to understand. You can of course extend Raphael to use a more simple syntax:
Raphael.fn.polygon = function () { // supply x,y coordinates as arguments
var self = this.path();
self.coords = [];
for (var i=0;i<arguments.length;i++) self.coords.push(arguments[i]);
self.update = function () {
var pathlist = [];
// the M command moves the cursor:
pathlist.push('M'+self.coords[0]+' '+self.coords[1]);
// the L command draws a line:
pathlist.push('L');
// Now push the remaining coordinates:
for (var i=2;i<self.coords.length;i++) {
pathlist.push(self.coords[i]);
}
// the Z command closes the path:
pathlist.push('Z');
self.attr('path',pathlist.join(' '));
}
self.update();
return self;
}
Which should allow you to do:
<div id="MyArea"></div>
<script>
var paper = Raphael("MyArea",640,480);
var mypolygon = paper.polygon(
10, 10,
20, 20,
10, 30
);
// you can even modify it after creation:
mypolygon.coords.push(15,20);
mypolygon.update();
</script>
Or create your own polygon API to taste if you don't like mine.
EDIT: fixed some small bugs.
I agree with slebetman that Raphael is totally great. Note, however, that neither SVG nor VML is currently supported in the Android browser. Canvas with excanvas.js may be a better bet for cross-browser work, if you are also targeting Android.
Also, if you really want to use the Google Map API, you can simply hide the map. But you would still be stuck with the Google logo due to the Terms of Use.
You can do this by using a tile with a single color in v2, but I believe there are other ways do this in v3.
Example of the v2 method: http://fisherwebdev.com/california
Example of hiding some of the map features in v3: http://fisherwebdev.com/mapcolors -- You can use this same technique to hide all features.
Play around with this to see what is possible to hide/show or restyle in v3: http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html

Problems with animateAlong in IE7

I'm having trouble making a simple shape move along a path in IE7 (the only version of IE I tried, actually). The following code works fine in chrome and firefox, but not IE. I couldn't find an obvious reason, has anybody seen something similar?
canvas.path(rPath.path).attr("stroke", "blue");
var circle = canvas.circle(rPath.startX, rPath.startY, 5);
circle.animateAlong(rPath.path, 3000, true);
My rPath variable has the path and the starting point coordinates.
Microsoft script debugger points to this line as the one where the code breaks:
os.left != (t = x - left + "px") && (os.left = t); (line 2131 inside the uncompressed raphael.js script file, inside Element[proto].setBox = function (params, cx, cy) {...})
Any ideas? Any experience (good or bad) with raphael's animateAlong in IE7?
TIA,
Andrei
Create a circle using a real path..
Take this code...
paper.path('M325 35a200 200 0 1 0 1 0' );
and play with it here...
http://www.irunmywebsite.com/raphael/additionalhelp.html?q=animateAlong
It turned out to be the original coordinates of the moving circle, rPath.startX in my example. It was obtained by splitting a string, therefore a string value. While the positioning of the circle worked fine, the animateAlong was not as forgiving in IE.
Parsing it to an int before using it fixed the issue.

Categories

Resources