Nested SVG elements with Raphael - javascript

Trying to implement nested SVG elements with Raphael.
I think this Question is related to
https://groups.google.com/forum/#!topic/raphaeljs/tzdj3y2DDwg
Any solution? Thanks.

Actually, I've maneged to partially implement nested svg approach.
This is a short example:
var outer_svg = Raphael(document.getElementById('container'), paper_width, paper_height);
outer_svg.canvas.setAttribute('id', 'outer_svg');
var inner_svg = Raphael(document.getElementById("outer_svg"), paper_width, paper_height/2);
inner_svg.canvas.setAttribute('y', paper_height/2);
Here we created inner_svg that is half the height of outer_svg and is positioned at the bottom of outer_svg.
The canvas object represent the svg dom element. So if we give it an id attr then we can adress it to be the parent of another svg. And we can set the x,y coords relative to parent svg element.
Now the sad part:seems that canvas doesn't support animation method, so we cannot animate the whole svg child element. Sets don't help here because drawing elements parts that are outside child svg canvas disappear (as they should).

Related

Create SVG elements from collection without explicitly setting coordinates

I'm new to SVG, so I don't know if I'm missing something obvious and simple.
In every lesson on creating SVG elements, x and y coordinates must be explicitly set for element to be drawn. But is there a way for a browser to draw one svg shape right next to another, without explicitly specifying coordinates, like DOM does when you write <div>content1</div><div>content2</div>?
What I want is:
Having a collection of data for elements (let's say, they are all rectangles with only width and height specified), is there a way to draw all of them sequentially in a row (horizontally)? I don't want to manually set coordinates for each element, just call foreach element in array and expect browser to figure out coordinates from each element's width property.
Is this achievable only with some script that dynamically calculates bounding box for each element or there is some simpler way?

Snap.svg bounding box not updated on child elements after applying transform to parent g element

Codepen: http://codepen.io/anon/pen/dfIBv
I have two rectangles in g element on which I apply transform. GetBBox method shows same numbers after and before transform.
If I apply same transform directly on those rectangles, getBBox method shows correct measurements.
Is there any way how to get "correct" measurements of these rectangles after applying transform to parent group element?
Thanks!
Ian is correct. element.node.getBoundingClientRect() shows correct measurements. Thank you :)

How to make a svg element (e.g. rectangle) scrollIntoView?

I have a svg in graph panel. All nodes in the svg are listed in another panel. I hope that by clicking the node in node list, svg can scroll to that node. Each node is a rectangle. But I found that only the upper border is in view, while the rest part of the node are still out of the view. Is there any way to fix this problem? (either Javascript or Extjs)
This is my code:
function selectRectangle(Id){
var ele = Ext.get(Id);
ele.scrollIntoView(Ext.get('graph-panel-body'), true);}
By whatever reason scrollIntoView seems not to work for SVG elements. This is what I do
suppose the svg is in a
<div id="container">
<svg ...>
...
<path id> ...</path>
</svg>
</div>
then suppose in the variable 'element' you have the element you want to scrollIntoView
var bbox = ele.getBBox()
var top = bbox.y + bbox.y2
top = 50 * Math.floor(top/50)
$("#container").get(0).scrollTop=top
I am not sure, but I observe that getBBox is pretty slow. So take care.
The problem is that the SVG element you are trying to scroll the view to probably has a y or dy attribute which offsets it from the top, and the scrollIntoView method in Chrome doesn't take that into account (in Firefox it does), therefor it will scroll to the top, because it thinks the element is there, because this is how SVG elements positioning works.. elements are all rendered from the very top left and then kind of "transformed" to their positions via x, y, dx, dy attributes.
There is an open bug which you can (and should) star:
https://bugs.chromium.org/p/chromium/issues/detail?id=803440

adding padding to svg g element

my d3.js code generates the following HTML (this was taken from inspect element)
The paths render a circle with text at the bottom of it.
Ultimately I want the text to be UNDER the circle within the bounds of the SVG element. If the SVG element is larger, the G element renders larger. I need to control either the size of the G element or the size of the path elements.
How would I add width and height constraints or padding to the G element? It doesn't respond to width, height, x, y in style
cursory google search was not very helpful
thanks for any insight.
The <g> element doesn't really render at all, it's the <path> and <text> elements you need to adjust.

Put Raphael (SVG) canvas behind other divisions to make them clickable?

I am using Raphael to create lines between divisions in an organization chart (or flow chart), but I need to be able to actually click on the divisions and content behind it.
If I could make the canvas be behind the other elements, kind of like a background image, that would be idea. Is this possible?
I found a solution. Raphael makes an SVG canvas that is absolutely positioned in my case. Absolute positions act as layers, and so to be on top of that layer, my content had to be absolutely positioned as well.
If someone else has a better solution, I would be happy to hear it, though this is working fine.
What I do is create a layer of invisible (but clickable) shapes on top of the informational lines being rendered, which will act as the target area for the content below.
If your lower layers being target are being created in Raphael you can easily clone them, set the opacity to 0, and position that layer to the top. (See Sets Reference for a way to easily group the layers together.)
Example:
#el = #parent.paper.rect(x,y,w,h); //your existing lower layer shape definition
#elTrigger = #el.clone(); //clone your existing shape
#elTrigger.attr
fill: '#fff'
opacity: 0
cursor: 'pointer'
#elTrigger.click(someAction); //assign the function
If you're lower layer isn't being rendered by Raphael (just HTML) you could still do something similar, but it would require just creating new (transparent) shapes to sit on top of the approximate coordinate of the targets below.

Categories