Zoom in SVG with currentScale - svg

I've a web page in which there is a SVG box <svg id='graph'>...</svg>.
I would like to give to the user the possibility to zoom in the SVG box.
I use for this purpose document.getElementById("graph").currentScale*=2; if I want to double the size of the box, for example.
The problem is that all the window is resized, even the HTML elements outside the box.
Do you know the origin of this problem please ?

In order to apply zoom to only svg , use this...
<svg>
<g transform="scale(2)">
</g>
</svg>

This may be off the mark without knowing which browser you're using, but you may not be able to implement currentScale if you're using anything other than Internet Explorer or Microsoft Edge. You can test this for yourself by trying this JSBin in different browsers and see where it scales.
Diving into this deeper, a Google search of "SVG currentScale" found these bug threads from Google and Mozilla discussing similar issues. The Mozilla thread discusses it was a choice made specifically for consistency's sake. SVG's currentScale only applies to container elements and not to inner elements. This could interfere with functions like zoomAndPan used on inner SVG elements. Additionally, better cross-browser solutions are already in place such as scale() via the transform property.

Related

SVG styling not applying in illustrator

I'm generating an SVG in a web app and allowing users to save it; the SVG embeds the styles in the header of the image.
When a user opens it in their browser (testing in Chrome) it style properly:
However in Illustrator it seems the styles aren't being applied:
What am I missing? Download the actual SVG here.
The problem is really with Illustrator's SVG importer.
You probably have to choose between two solutions:
Tell your users that saved SVGs won't work with some programs (like Illustrator)
Modify your graph generating code so that it doesn't rely on CSS classes.
For example: change the elements that use
class="link"
To instead set the style properties explicitly:
fill="none" stroke="#aaa" stroke-width="2px"
Or maybe you can find a script on the net somewhere that does that for you.

svg elements - scroll to/ centering

I've an svg dynamically created on a page. As things "happen" (user clicks) the svg expands and collapses certain elements. It may fit in the viewport, it may not. In the case that its too big to fit on a page, the user must scroll to where s(he) wants to go/see. Now this is fine, however I have a requirement that the last element "selected" becomes the center of the page/viewport. i.e. If they click on an item, thats what they need to see without scrolling.
Could anybody tell me the best way to attack this. I've googled around but can't find what I'm looking for (though I'm not long at all this so I might have been searching the wrong stuff).
Is there a way to do this purely programmatically with javascript? Or am I obliged to pass by CSS to get the solution I want. Any tips/links/advice much appreciated.
thanks and have a nice day
G
I had a similar thing and I used the viewBox property to handle this. You could also use a wrapping <g> element, which you translate. However, from my point of view the basic approach is the same and you basically need to do two things:
keep track of the x and y offset and the dimensions of the viewport. (Using the viewBox will give you that »for free«)
Compute the center of the Element. Therefore I used the getBoundingClientRect()method which yields the AABB of of the Element in absolute coordinate space, relative to top-left edge of the whole page.
With these things, all that remains is to calculate the vector from the viewport center to the object's center.
Here you can find the reference of the viewBox and here a nice tutorial about it, because it can be a bit confusing at the beginning.
Another pro for the »viewBox« approach is: There is no dependency on special DOM elements, it just works on the root <svg> element. I once implemented both methods, I started out using a wrapping <g> element, what worked fine but gave me some performance issues. So I decided to change and use the viewBox, with the result, that the performance in Firefox grow, but slowed down in Chromium.
Edit
Here you can find a little fiddle, that outlines the approach. But be aware of the following: getBoundingClientRect() yields the position of the Element on the whole Page, so if your <svg> is not positioned at (0,0) (top: 0px; left: 0px), than that will include the offset of the svg itself. The offset of the viewBox must not include this offset, so you need to cancel that out somehow. For sake of simplicity I just used the client Bounding Rect of the SVG, what works because there are no transformations applied.

SVG 'maskContentUnits' not rendering properly in mobile safari

I have an SVG I am building with Javascript. I load in a large SVG file, break it apart into pieces all drawn with paths, and place each element in my page. I'm only using these SVGs as masks for other images I am loading. Basically my structure is like the following.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="26.750152587890625 10.117172241210938 197.24969482421875 348.1596221923828" width="197.25" height="348.16015625">
<mask id="designMask" maskContentUnits="objectBoundingBox">
<g id="CutContour1bg">
<path d="[my path coords]" style="fill:#FFFFFF;">
</g>
</mask>
<image href="http://myImage.jpg" style="mask: url(#designMask);" width="800px" height="800px" x="26.75" y="10.1171875">
</svg>
This renders the image being masked by my SVG perfect, in FF, IE9, Chrome, Safari 5.1 (desktop). In mobile safari however, the image does not render properly. I trace out coords of the mask, they are all correct. In FF I can see the SVG load (all black) then disappear as it becomes the mask. (I am waiting until the design is loaded, then wrap my <g> with <mask> since FF has an issue looking for the mask before the content is loaded.
This tells me the mask's position is exactly where it needs to be, but the maskContentUnits are not. They remain in the top left corner instead of the object's bounding box, like I'm telling it. I can barely see part of the image in the mask, so the mask units are correct, but I cannot get the maskContentUnits to work or be read in mobile safari.
Has anyone ever seen this issue, or any idea how to correct it? I hate having this work everywhere except mobile safari, as it is meant to mostly work on mobile... which defeats its not purpose haha.
Thanks!
I haven't found a way to make maskContentUnits work properly in mobile safari yet, I'm pretty sure it's just not recognized yet like other browsers. But I figured out a 'hack' to make the example work.
The issue is, the mask area resides in the top left corner of the browser, rather than of the svg object being used as the mask. So if you have an svg in the middle of your page, the image being masked will not follow the same positioning.
The way I found for it to work, is, I wrapped the svg inside a div with the same width as the svg, and modify the position of the div instead of the svg. This way the mask is technically still in the 'top left' corner, but of the div rather than the offset position of the svg.
If anyone finds a better way, to make maskContentUnits render proper in mobile safari, I'd like to hear it!

Issue with SVG display / rendering in Fabric.js

I'm using FabricJS and I encounter a problem with the display of my SVG in the canvas:
the result is displayed outside the selection box of fabricJS (due to a translation ?)
the anchors of the selection disappear after a transformation and then it's impossible to find them back.
Here is a screenshot :
I'm using an output SVG of Potrace and I think it's the origin of my issue.
Here is the code of the SVG: SVG code in pastebin
You can test it with FabricJS on this page: FabricJS Kitchensing example.
Just paste the code of the SVG in the "Load SVG" area, then resize and rotate the section box to display the SVG.
Do you know the part of my SVG code or the part of the fabricjS code that causes the issue ?
If so, can I change it easily by myself ? If not, is it possible for anybody to correct or locate the possible mistake?
Thank you very much for your help.
EDIT: seemingly, FabricJS doesn't like this line of the SVG:
<g transform="translate(0,648) scale(0.098780,-0.098780)" fill="#000000" stroke="none">
And more especially the translate and scale attributes… How to fix it?
EDIT2: the solution would be that the translate and the scale are respectively equal to (0,0) and (1,1) or, better, that they're applied to the coordinates.
Does anybody have an idea to do that with Potrace or JS script?
2 years after, fabricJs is now able to fully parse and manage this SVG.
Just paste the old pasteBin SVG code in the kitchenSink demo and you will see that it loads fine.
Lots of improvement happened recently in the SVG parsing area.
I know this is not an answer as stackoverflow user would expect, but better to know that to think this is may still be a problem.

Rollover overlays with SVG

i want to acheive the effect on this page using SVG. As you can see it uses a series of PNG transparent overlays when the user mouses over a polygonal hotspot drawn on a product.
What i want to achieve is the same thing with SVG, but without messing about with creating a load of PNGs, so that when the user mouses over an area the transparent shape (with link on it) appears over the top. The SVG shape would be built from a set of coordinates exactly as a polygonal hotspot would on an image map.
So i guess my first question is, can this be done with plain old SVG or do i need to use something like Raphael to achieve this? Never seen this effect before with SVG so if anyone has an example like that would be very useful.
Thanks in advance.
There are several ways to get this effect with plain old SVG. Probably the simplest is to use CSS within the SVG. For example:
<style>
.overlay:hover
{
opacity: 0.5;
}
</style>
<svg>
<a xlink:href="http://www.wherever/you/want/to/link/to.com">
<path class="overlay" d="Coordinates of your shape..." />
</a>
</svg>
I've written about various other methods at:
http://www.petercollingridge.co.uk/data-visualisation/mouseover-effects-svgs
Yes it can be done with SVG only, with or without javascript.
One way to get the effect would be to overlay a white semi-transparent path on top of the image that you want to whiten. Another way would be to use an SVG filter to process the image directly, similar to what I've done here or here to recolor a PNG (view page source and feel free to reuse that in any way you like).
You'll want to make use of the 'pointer-events' property most likely. Here's an example showing how to detect mouse-events on the fill and/or stroke of an svg shape, even if the shape is invisible.

Resources