I have a number of <circle> elements each inside their own <g>. To move the circles around I'm applying a "translate" transform on each <g>.
What I notice is that as the circles are moving, some of them seem to get slightly truncated. As soon as they come to rest they look just fine so it is just while they are in motion. The truncation effect looks something like what you'd see if you had a square viewport the same size as the circle and then moved the circle slightly out of centre. It just flattens slightly on one side.
This is what one of my element groups looks like:
<g class="datapoint dot" transform="translate(360,56)">
<circle class="rendering" style="fill: #3182bd; stroke: #225b84; stroke-opacity: 1; fill-opacity: 1; " r="7"></circle>
</g>
When I run the transition watching the debugger I can see the values in "translate" change but everything else stays the same. So it doesn't seem to be something I'm doing wrong, but you can never be sure of that. :)
One final comment is that I do see this in multiple browsers (tried Chrome and Firefox so far).
Has anybody encountered this kind of thing before?
Probably a bit late for you but I've noticed similar things when using transform: scale(). The SVG shape is limited to the files original size. If the shape gets enlarged bigger than this then it will be cropped.
My fix was to make the bounds of the SVG bigger than the shape itself so that it has some room to expand into.
Related
I have a couple of SVG images that I want to paste together to make a big graphic.
First, let me present you with my problem:
This is one of the symbols, placed in a grid. The grid is, for convenience, with unit-less 100 distance from line to line.
If I render it to pdf, it looks like this instead:
Those symbols have a completely wrong size for the grid (They are much larger, mostly) and they are badly positioned if I use them raw.
So my treatment is, I scale them and position them correctly in relation to the grid, then I make a rectangle around them that encompasses them completely and makes the symbol-handling easier.
That rectangle is perfectly fitting to my grid. In my case, for this symbol, it is a rectangle encompassing the six squares around the symbol. I did this, because the symbol can be rotated by the user and the rotation is done from symbol point of view; any transform after the rotation is from the rotated point of view. So I made an attempt to de-couple the transformations by wrapping them.
Finally, I move the rectangle to a user-defined place and rotate it as the user wants to have it. So far, so well, it was extensively tested in google chrome and works reliably. In Google Chrome.
Now I wanted to translate it to pdf for printing. And after conversion, the symbol is placed in the wrong position.
I am guessing (as I made several tests) that the error is somewhere in my header.
Could someone of you please check the headers that I add and tell me if and where I did something wrong? For example there is a view box starting at -100, otherwise the symbol would be cut and wrongly placed. Is there another way to "rectangularize" any arbitrary symbol? Or is it generally the wrong way to do these kinds of things?
Here are the changes that I added around the svg symbol code. Innermost changes are applied first.
<!-- move the rectangle to the right place and rotate it as the user wishes-->
<g transform="translate(300.0, 400.0) rotate(0,150.0, 50.0) ">
<!-- a rectangle around the symbol, perfectly fitting to the grid-->
<svg x="0" y="0" width="300.0" height="200.0" version = '2.0'
xmlns="http://www.w3.org/2000/svg" viewBox="-100.0 0 300.0 200.0">
<!-- scaled to correct size, placed inside the grid as it should be -->
<g transform = "translate(-10.000, 73.614) scale(0.229,0.229)" >
<!-- original symbol, wrong size -->
<svg width="523" height="230" version = '2.0' xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 523 230">
.... lots of svg paths here ...
</svg>
</g>
</svg>
</g>
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.
I am viewing the following svg http://pastebin.com/pNdNEQ6z in my Firefox and chome.
Can someone tell me why the two graphs are somewhere in der middle of y an not starting at the top? If you change the viewbox to "0 200 650 800" everything is fine. why 200? I have played with preserveAspectRatio="xMidYMin" but this is not doing anything.
At the end of the day I want to display both charts completely visible starting at the top? And I would like to understand why it is not doing so right now :-)
Your problem is that you had a typo on your first embedded <svg> element (you had hight="400" instead of height="400") and were not using a …YMin alignment on the outer.
Fixed, it looks like this:
<svg … preserveAspectRatio="xMidYMin">
<svg … height="400">
Demo: http://jsfiddle.net/WAVZj/
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!
I have one or more path elements inside a g element that I am scaling to fit inside a grid rectangle. The transform is applied to the g element. My transform works in that all the points end up at the right places, but I discovered that I have to adjust the stroke-width of the path to get a readable line.
The problem is that if the scale involves a large shift in the aspect ratio, I end up with some segments of the path being heavier weight than others, depending on their orientation.
Here is a typical transform that my code computed:
scale(0.1875, -0.010397820616798718) translate(-1149000, -96174)
In this case I end up changing the stroke-width from 9px to about 48px. Segments close to the horizontal end up thin, those close to the vertical are thick.
Is there any easy way to end with all the segments with the same rendered width?
Have you looked at setting the vector-effect attribute to non-scaling-stroke?
<line vector-effect="non-scaling-stroke" stroke="black" stroke-width="5"
x1="32" y1="50" x2="32" y2="350"/>
http://www.w3.org/TR/SVGTiny12/painting.html#NonScalingStroke
UPDATE
The best solution I can think of is to manually transform the coordinates of your path.
vector-effect="non-scaling-vector" is not consistently supported. My versions of Firefox and Safari do not support it, but my Chrome browser does.
In the SVG standard there is no way of specifying a transformation for the stroke independantly. (A stroke-transform attribute would be nice - like the windows GDI+ drawing system, where a Pen object has it's own local transformation).
Until this changes, the best solution I can think of is to manually work out the coordinates of your path - that is the svg has no transform elements; the coordinates are already transformed.