SVG Pie chart animation - svg

I have a pie chart svg image, which I get it from server. And my job is to apply animation to this pie chart on client side using snap svg.
Now, the problem is I am new to SVG and I don't know where to start, but I have succeed in animating other chart types.
Can anybody help me with some referral links to solve this problem. I got this link which implements this. But they have not explained how they have achieved this.
Any other kind of animation which can be achieved by snap svg for pie chart can also help me.
edit I have added fiddle of pie chart that I want to animate. I have tried this code:
Snap("svg").select("#pie2d").
animate({ transform: 'r360,150,150' }, 1000, mina.linear );
which does not animate each section of pie chart but complete chart as a whole instead.
This line does not get executed in fiddle as it needs Snap.js
Any help is appreciated.
Thanks in advance.

Snap animations are generally straightforward. Here is a relatively simple example that will introduce some of the elements you may need..load in a file, and animate it once loaded with hover (you must wait until load finish with file imports).
I couldn't put it on a jsfiddle as it needs a remote file, but have it on a test page here with the code below. Also the Snap website getting started page shows loading in svg and animating.
var s = Snap(600,600);
var g = s.group();
var tux = Snap.load("Dreaming_tux.svg", function ( loadedFragment ) {
g.append( loadedFragment );
g.hover( hoverover, hoverout );
} );
var hoverover = function() { g.animate({ transform: 's2r45,150,150' }, 1000, mina.bounce ) };
var hoverout = function() { g.animate({ transform: 's1r0,150,150' }, 1000, mina.bounce ) };
For transforms, they use the Raphael format (same author), which is loosely the following...
t=relative transform, T=absolute transform, s=relative scale, S=absolute Scale
r=relative rotate, R=relative rotate
r
elative means it takes into account previous transforms to accumulate
here it doesn't make much difference, until we combine later
For the specific pie chart, it depends if you already have that in the svg you are pulling from the server, so you may not need to know too much about pie chart creation. If you do, there are some other libraries which support pie charts already (by Raphael, d3.js etc)
I assume you will need to attach a hover element to each segment of the pie chart (you can use something like g.select("segment1")), and scale it up/out, like above.

Related

fabricjs: Issue with multiple paths of SVG having the exact same gradient

For my web app, I am creating SVG elements in Illustrator and then using them in a library of elements that users can add to the fabric canvas.
Some elements are simple but some complex with multiple compound paths etc.
I have came across an unusual issue where if I create a path with a gradient fill, and then copy that path, save the SVG and add it onto the canvas, only the first path would have the gradient and the rest would be flat colors.
Here is a screenshot of what I mean...
After experimenting and trying different things, I finally discovered that this is happening because the paths have the exact same gradient properties.
So if the gradient slider (color stops, opacity, location etc.) of two or more paths have the exact same properties in Illustrator, then the issue occurs.
So the workaround is to alter something like the location (for example) to be 99.9% instead of 100% on the copied path, then the issue goes away. However, this will quickly become a tedious and annoying way to fix this. Basically, each path with a gradient, needs to have a unique gradient set up and cannot be identical to another paths gradient properties.
Here are more screenshots to better explain...
After making this change...
The first and second path's gradient's location are different.
The first, third, fourth and fifth paths have exact same gradient.
This is what it looks like when I add it to the canvas now...
Here is the code I am using to add the SVG to the canvas...
fabric.loadSVGFromURL(image, function(objects, options) {
var oImg = fabric.util.groupSVGElements(objects, options);
oImg.perPixelTargetFind = true;
oImg.targetFindTolerance = 4;
canvas.add(oImg);
canvas.renderAll();
});
Can anyone tell me why this is happening and if there is a way to fix this with code rather than Illustrator? I have hundreds of elements to create that will have many paths with the same gradients. I know it will be a real pain to have to worry about paths not having the exact same gradient.
http://jsfiddle.net/oc70xjsq/
Link to the SVG

Creating an SVG Document in SVG.js issue?

I am new to SVG.js and javascript in general, and I was going over the documentation here http://documentup.com/wout/svg.js#usage/svg-document and was having some issues.
Usage
Create a SVG document
Use the SVG() function to create a SVG document within a given html element:
var draw = SVG('drawing').size(300, 300)
var rect = draw.rect(100, 100).attr({ fill: '#f06' })
so I was assuming from this they want us to call a function so what I've gathered from messing around a little in Three.js is that I need to do
<script>
function SVG()
{
//Use the SVG() function to create a SVG document within a given html
var draw = SVG('drawing').size(300, 300)
var rect = draw.rect(100, 100).attr({ fill: '#f06' })
}
</script>
within the body tag. This doesn't work however. When calling SVG(); I get an error
Uncaught RangeError: Maximum call stack size exceeded (15:22:47:898 | error, javascript)
at SVG (:18:13)
at SVG (:20:12)
at SVG (:20:12)
at SVG (:20:12)
at SVG (:20:12)
at SVG (:20:12)
There are other ways I can do it as mentioned, but it seems that the easiest method would be to call a function, but again I'm not sure if I'm doing this correctly.
I have a background in Java, just getting off of a project with JMonkeyEngine, so I'm not new to programming, but confused with what exactly I need to do with this, since the documentation is extremely vague and seems to suggest that you need to understand their terminology as to where to put the code.
I have also found a few other librarieslike snap.svg, d3, and raphael
http://d3js.org/
raphaeljs.com/
snapsvg.io/
I'm really just trying to create a bunch of pictures/colored boxes (interchangable so essentially a box with an image that can then be turned off and be displayed as a color) with borders, that can respond to mouse even of clicking and dragging around on desktop and mobile browsers. Essentially not much, but it seems like these all have similar features just a different coding feel.
Any advice?
Thank you everyone!
As said by Nils, there is a Hello World example here: https://stackoverflow.com/tags/svg.js/info
You also find plenty of documentation and examples to see what you have to do.
//Use the SVG() function to create a SVG document within a given html
var canvas = SVG(idOfElement)
// now an svg was created in the element with the id
// draw a rectangle
canvas.rect(100,100)

How do I rotate or scale (transform) an SVG path relative to its center point?

I'm trying to rotate and scale shapes within an SVG around their center point. I've looked into several libraries, including Jquery, Greensock, D3, RaphaelJS, but I haven't been able to find any that provide a straightforward way to accomplish this. Each animates the shape from the origin point (which I understand is the default). I want to be able to spin a shape around its center point or scale it up or down from the center point.
Here are a couple examples using Greensock and D3 that illustrate the default behavior: http://jsbin.com/AHEXiPa/1/edit?html,js,output
Each of these examples bounce in and out from the top left as opposed to remaining stationary and expanding from the center of the triangle out in all directions.
Can one of the libraries I mentioned accomplish this, or is there another library or method I should consider?
Ideally, I need to be able to apply the animation/transform to an existing object in the DOM. D3 is good at this for instance, but Raphael seems to require converting an SVG to Raphael first prior to injecting it into the DOM.
Really its a case of pick the library that suits your needs, and then you will figure a way. As BigBadaboom says, if you do a search, there are lots of solutions.
To try and combine your questions, as sometimes the tricky bit is using an existing DOM object, I've included an example in Snap.svg. You can often do something similar in most libraries.
jsfiddle here Fiddle using your existing html.
s = Snap("#mySVGContainer1"); // create a canvas from existing svg
var triangle1 = s.select("#myShape1").transform("r90"); //select&transform existing object
p = Snap("#mySVGContainer2");
var triangle2 = p.select("#myShape2");
var bbox = triangle2.getBBox(); //bounding box, centre cx/cy
//rotate and scale with transform string (raphael/snap format)
triangle2.animate({ transform: "r180," + bbox.cx + ',' + bbox.cy + "s3,3," + bbox.cx + "," + bbox.cy }, 2000);
For rotations, as #Ian points out, you can specify the center of rotation. For other transformations, changes are defined relative to the path's (0,0) point.
The easiest way to get transformations to work relative to the path's center is to either:
Define the path so that it is centered around the (0,0) point; or
Wrap the path in a <g> element, and then translate it so it is centered on the (0,0) point of the <g> element's coordinate system.
Then, you can apply rotations, scales and transforms (on the <g> element, if using) and they will all be nicely centred.
The trickiest part is figuring out the "center" of an arbitrary shape. #Ian's approach of using the center of the bounding box will usually give decent results. If your shape is a polygon there are d3 functions you could use.
Example showing a shape moving with the mouse, rotating and changing scale, all centered around the center of the bounding box:
http://fiddle.jshell.net/LgfE3/
Edit: simplier jsfiddle
I've been looking for a long time, and will settle for the following.
1. Design your svg shape at coordinate x:0,y:0.
2. Identify by hand the center of rotation, by example, center = [ x:50,y:100].
3. Build a spinIt() function such :
function spinIt() {
needle.transition()
.duration(2000)
.attrTween("transform", tween);
function tween() {
return d3.interpolateString("rotate(-180, 50, 100)", "rotate(90, 50, 100)");
}
}
4. Use it on a triger:
svg.on("click", spinIt);
http://jsfiddle.net/SHF2M/79/

Scale an SVG (in Dart) using viewBox doesn't work

I recently started working with Google Dart (www.dartlang.org) and playing with SVG.
I am trying to scale a generated SVG to fit into a <div> using a viewBox.
People on StackOverflow already gave me a lot of help.
I am now able to scale paths like this: Dart create and transform an SVG path
But is seems that viewBox is made for scale-to-fit and using it would save me from scaling all paths in the svg separately. That is why I want to use a viewBox.
I tried the following:
// get bounding box of the created svg
Rect bb = path.getBBox();
// create a viewBox for the svg to fit in the div
var viewBox = svg.viewBox.baseVal
..x = bb.x
..y = bb.y
..width = bb.width
..height = bb.height;
// center the image inside the div
svg.preserveAspectRatio.baseVal
..meetOrSlice = PreserveAspectRatio.SVG_MEETORSLICE_MEET
..align = PreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID;
But no scaling happens.
How would I solve this?
While writing this question and retrying to make sure I tried anything before asking here, I found the following solution.
It seems like Dartium (Chrome with a native Dart VM) has a bug (issue 12224) where changes to the viewBox are not reflected directly.
Adding the following code after changes to the viewBox forces Dartium to somehow resize to the requested size:
// add an empty ```<g>``` element to force svg resize
SvgElement g = new SvgElement.tag('g');
svg.append(g);

Graphael pie chart legend overlap

I've been using gRaphaël charts for a few weeks now, and every now and then I get some weird issues. A recurring theme is that the pie chart legend labels all get squish together in the wrong places. Picture > words:
The chart is created as you would expect, in this case:
var r = Raphael(domNode, 300, 120);
this.chart = r.piechart(55, 55, 50, [75, 25],
{
colors: [
"000-#d00-#900",
"000-#3a3-#070"
],
legend: ["Building", "Tertiary Education"],
legendpos: "east"
});
I then do some more basic styling, but turning that off doesn't help. The problem is clearly visible in the <svg> node (the text and circle nodes share overlapping positions), but I don't know where it comes from or why, and it only happens sometimes; other charts work just fine. There's nothing on the forums or issue tracker either, though I just realised I should probably ask there instead/as well.
Using Raphaël 2.1.0 and g.Raphael 0.51.
I have found the following blog post which deals with this exact problem. If the pie chart is rendered in an initially hidden element, gRaphael has problems to compute the positions properly resulting in this stacked legend:
So the solution is to render the facebox partial first, after the
facebox is shown, then you execute the Raphael Javascript. In other
word, make sure you generate the chart when the chart container is
there and not hidden!
I have solved this by moving the create pie chart function from the jQuery document ready directive to the on click event that will make the hidden elements visible.
Try to define your legend as following
{ legend: ["Building", "Tertiary Education"] , legendpos: "east"}
Its the only difference taht I could find between your and my working jsfiddle

Resources