I need to replace part of SVG image (map of hall seats) and it doesn't work as I would expect.
I have <g transform="translate(383.25,-48.882672)"><g .. node containing few rect and path elements which build an icon. I can find g by class with jQuery and .html(other_path_content) which makes content appear in the original size (too big to fit the original item spot). When I resize new icon <path d=.. manually and html it again, it goes off the place and appears in different location than original icon.
The problem here is that SVG images I get are random so I can't calculate place of the original icon and transform it to be there as it will be different everytime.
Is that possible to somehow calculate position of the original element and its size (mind it contains of few rects and pathes) and put new one on exact same place? Or maybe I'm missing something in my approach (do I need to re-init svg after appending new node etc.)?
Related
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?
Does anyone know why the behavior displayed in the above images might be occurring? In the first image, the x and y coordinates of the svgArcs container are set to zero so the center is in the top left corner and only the bottom right corner is displayed, as expected. In the second image, I moved the container, but still only the bottom right corner is displayed. I posted the document structure so maybe you can take a look and tell me what's going on.
By default <svg> elements clip their contents.
You could specify overflow="visible" on them or alternatively (and better) use a <g> element as a container rather than an <svg> element. You'll still need to keep the outermost SVG element an <svg> element.
I have a group, inside of which is an image. I've got code working so you can zoom with the mouse wheel. When the zooming stops, I reload the image, in a larger size. I add the new image to the group ( the old image is still part of the group ) and then I do this:
img.remove();
img.destroy();
imgNew.moveToTop();
imgNew.offsetX = offset.x;
imgNew.offsetY = offset.y;
At the end of this code, my old image disappears and the new one is not visible. It has a position that is sane, and it is the child of my group. It has exactly the size I expect it to have ( it's absolute position is 0,0 and it's size is bigger than my canvas ). I've turned off clipping, so if it was visible anywhere, I'd see it. I've changed the position in the debugger, and called draw() on the canvas, the layer and the group. I have dragging code and I've dragged the drag control ( which is still there ) every where I can. I've also changed my code to just add the new image to the top level layer instead of the lower down group.
I should mention in case it's relevant, the image is coming from a WebAPI RESTful service, and the size is passed in, so the image URLs are different for the two images.
I simply cannot find my image !!! What should I do next ?
This:
KineticJS - How to Change Image src on Button Click
answered my question. Short version: there's a setImage method so you can load a new image, call setImage() and it gets replaced.
We have code that loads SVG via Ajax and interacts via Javscript. The SVG represents wiring diagrams - that is paths ('wires') and text ('labels for wires'). The paths and text objects are grouped under a node - each node also contains a node: using ID's we place in the desc node we can respond to the click - e.g. by popping up details of the ;selected wire'.
In general the system works perfectly - but occasionally the SVG click event we get back seems to belong to 'another wire'. Here is an example of the geomtry when this happens:
---------------
-
-
....... -.....Wire1....
-
-
-
------Wire2--
(I hope this is clear - Wire1 runs horizontal, Wire 2 is a zig zag shape, running vertically as it crosses Wire1)
In this geometry the behaviour we see is:
Click on Wire1 Path --> event points at Wire1 Path
Click on Wire1 Text --> event points at Wire2 Path (!Wrong)
Click on Wire2 Path --> event points at Wire2 Path
Click on Wire2 Text --> event points at Wire2 Text
Changing the z order (Writing Wire1 After Wire2 in the SVG file) has no effect.
Representing wires by a series of short paths (rather than one long path) fixes this issue but increases the files size (and these wiring diagrams are massive).
One would like to thing this was just one bug in one SVG browser - but it is observable in Safari 5 and Mozilla. (Which I assume do not share a common code base). Which suggests that under some circumstance SVG defines the 'active clickable area' of a Z shaped path to be its bounding rectangle.
How can we control this? Is there a header tag attribute or other work round that would restrict the active area of any path to the path itself?
If you have a fill on your paths (even one the same color as your background) that would clearly explain this. Do you have a test case you can share showing the problem?
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.