SVG - scaling issues with images - image

Scaling a parent DIV containing an SVG that has image over a colored rect shows hairline edges from the underlying rect.
<div style='transform: scale(0.79454)'>
<svg width="1280" height="720">
<rect fill="yellow" width="1280" height="720"/>
<image width="1280" height="720" transform='matrix(1.4,0,0,1.4,-200,-150)' xlink:href="https://storage.googleapis.com/firebase-beautifulslides.appspot.com/test/dawid-zawila-279995.jpg"/>
</svg>
</div>
In the screenshot below, there is a yellow box beneath the image. Both are the same size but you can see the yellow box "bleed" out from the edges a bit (you may to view the full image or the fiddle below to see it clearly).
This artifact happens whether or not I transform the image node and also appears when I try scaling the SVG using a viewBox instead of the parent div. It's somewhat better in Safari than in Chrome but it does still happen in certain cases.
Here's a fiddle https://jsfiddle.net/e17ea4j5/
Is there any fix to this?

What you seeing is the result of anti-aliasing. The semi-transparent pixels at the edges of the yellow rectangle are visible through the semi-transparent pixels at the edges of the image.
There isn't really any elegant solution to eliminate those issues. Especially when when you are scaling by fractions (eg. 1.4 and 0.79454).
You are left with somewhat hacky solutions like putting a black stroke around your rectangle.
<rect fill="yellow" width="1280" height="720" stroke="black" stroke-width="1"/>
body{
background: black;
margin: 0;
}
<body>
<div style='transform: scale(0.79454)'>
<svg width="1280" height="720">
<rect fill="yellow" width="1280" height="720" stroke="black" stroke-width="1"/>
<image width="1280" height="720" transform='matrix(1.4,0,0,1.4,-200,-150)' xlink:href="https://storage.googleapis.com/firebase-beautifulslides.appspot.com/test/dawid-zawila-279995.jpg"/>
</svg>
</div>
</body>

Related

Image inside SVG shape path renders as black in Safari

I have a really odd Safari bug. I have an image inside an SVG shape path, here's the code:
<svg viewBox="0 0 367 367" height="367" width="367" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="bias" height="100%" width="100%" patternContentUnits="objectBoundingBox" viewBox="0 0 1 1" preserveAspectRatio="xMidYMid slice">
<image height="1" width="1" preserveAspectRatio="xMidYMid slice" xlink:href="https://upload.wikimedia.org/wikipedia/commons/c/cb/ADAC-Zentrale%2C_Munich%2C_March_2017-01.jpg"/>
</pattern>
</defs>
<path d="M0,183.5 L0,0 L183.5,0 C284.844252,0 367,82.1557484 367,183.5 C367,284.844252 284.844252,367 183.5,367 C82.1557484,367 0,284.844252 0,183.5 Z" fill="url(#bias)"></path>
</svg>
The image renders fine on the home page but the same code on all other pages renders the shape as black and no image, although in the inspector I can see the image is loaded. All other browsers it's fine.
The left shape is an example of it rendering correctly on the home page and the right is how it renders on every other page. Same template, same code.
Any ideas? Been pulling my hair out for hours, thanks.
Turns out it was a <base> tag in the head messing with the relative url.
Similar issue to this issue SVG Gradient turns black when there is a BASE tag in HTML page?
Thanks

SVG Image element resize picture

So i'm busy with SVG and i need a couple of images in my project. So you have the element . You can also give the height and width. The given picture doesn't resize to the height and width you give to the image element.
I have this code:
<g class="node image" transform="translate(0,129.652067739873)" type="ad">
<image href="content/image/image.png" height="30px" width="100px" y="41.94444444444444" x="0">
<title>google.nl</title>
</image>
<text y="56.625" x="106" dy=".35em" text-anchor="start">google.nl</text>
</g>
Now i want that the image.png cover the whole image element. Like background-size:cover; But that doesn't work, and i can't find any attribute who can do this. Is there a way to do this in a correct way?
Try setting preserveAspectRatio="none" for the <image> element. Also, if you want it to cover all of the svg, set width and height to '100%'
<image href="content/image/image.png" height="100%" width="100%" y="41.94444444444444" x="0" preserveAspectRatio="none">

Scale an entire SVG image to a new size without having to update the sizes of all the objects in it

I have an SVG image that specifies a specific height and width. All the objects in the SVG image are created to use this width and height. Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="600">
<g>
<circle cx="300" cy="300" r="295" fill="red" stroke="black" stroke-width="10"/>
</g>
</svg>
Which makes a 600 pixel red circle with a black border:
How do I scale this SVG image (to say 200x200) without having to go through and update all the objects (in this case just the red circle) contained within it?
To resize an SVG image you need to introduce a viewBox attribute that contains the the original size pixels. Then you can change the width and height to whatever you want.
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="200" viewBox="0 0 600 600">
<g>
<circle cx="300" cy="300" r="295" fill="red" stroke="black" stroke-width="10"/>
</g>
</svg>
That way the coordinate system to which the image is drawn is still the original 600x600, but the image displays scaled to 200x200.
Alternate method: assuming that all these SVG images are individual files, you can use either <object>, <embed> or <img> tag to reference this SVG file, then set width=200 and height=200 to rescale it.
Eg: <img src="path/to/somefile.svg" width="200" height="200"...../>

Chrome 34 SVG Bug

I have a d3.js application that renders images as nodes in a connected graph. After Chrome was updated to 34.0.1847.131, modifying opacity style attribute on an image causes display weirdness. Images and other svg elements will disappear or become partial rendered. I have tested in Chrome 33.0.1750.117, as well as recent Firefox and IE versions and they each work as expected.
I created a plunker to demostrate this: http://plnkr.co/1jKDh5JMiuxouQyqZzGy.
If anyone can give me a workaround or if there is something incorrect in my plunker, please let me know. Otherwise, it appears to be a bug with Chrome 34. I have reported an issue on Google Chrome forums, and there is another post on the Google Chrome forums with a similar issue.
My Chrome forums post:
http://bit.ly/1lXTHs0
Another user's Chrome forum post:
http://bit.ly/1ilYMsZ
As a temporary workaround:
The problem with one element's opacity affecting others seems to only apply to sibling elements. So one solution is to wrap each element inside its own <g> element (but still apply the changes in opacity to the element itself).
This SVG code displays fine:
<svg>
<g transform="translate(50,30)">
<g>
<image class="node" xlink:href="http://i.imgur.com/GInbcOj.png" x="100" y="50" width="50px" height="50px" style="opacity: 0.30000000000000004;"></image>
</g>
<g>
<image class="node" xlink:href="http://i.imgur.com/GInbcOj.png" x="300" y="50" width="50px" height="50px" style="opacity: 0.30000000000000004;"></image>
</g>
<g>
<image class="node" xlink:href="http://i.imgur.com/GInbcOj.png" x="200" y="50" width="50px" height="50px"></image>
</g>
<g>
<rect class="node" x="100" y="150" width="50" height="50" style="opacity: 0.30000000000000004;"></rect>
</g>
<g>
<rect class="node" x="300" y="150" width="50" height="50" style="opacity: 0.30000000000000004;"></rect>
</g>
<g>
<rect class="node" x="200" y="150" width="50" height="50"></rect>
</g>
</g>
</svg>
Live example with comparison against the SVG from your original code
For your simple d3 code example, this only requires some extra append calls:
var nodes = svg.selectAll("image.node").data(nodeData);
nodes.enter().append("g").append("image")
.attr("class", "node")
/* ...*/
svg.selectAll("image.node")
.filter(function(d) {
return d.id <= 2;
}).transition().delay(1000).style("opacity","0.3");
var rects = svg.selectAll("rect.node").data(nodeData);
rects.enter().append("g").append("rect")
.attr("class", "node")
/* ...*/
svg.selectAll("rect.node")
.filter(function(d) {
return d.id <= 2;
}).transition().style("opacity","0.3");
However, note that the entering elements added to your selection are now the <g> elements, not the shapes, so you need to re-select them before you can modify the shapes themselves. Your example code already did this, but not all examples would.
It's not ideal — beyond the extra code, you're doubling the number of DOM elements, which could slow things down if you have a lot of elements to start — but it's fairly straightforward to implement now and then remove later once most Chrome users have updated to the patched version.

SVG cannot set width and height in firefox

i am tying to solve this problem that is very annoying....
a simple structured html, with an svg element with the width and height of 700px:
<div id="wrapper">
<div id="gameZone">
<div id="background">
<svg id="svgRoot" width="700px" height="700px">
<circle cx="355" cy="600" r="10" id="ball" />
<rect id="pad" height="15px" width="150px" x="280" y="670" rx="10" ry="20"/>
</svg>
</div>
</div>
</div>
the question is why the hell the svg is displyed without the width and height in firefox?
in chrome and ie its working 100%;
please help me solve this problem.
here is an screenshot of the problem: http://shaharmesh.hostingsiteforfree.com/differance.jpg
Firefox debugger show the size as same as the result by svgRoot.getBBox(), the actual svg content bounding size.
To avoid the problem, place a invisible rect which has the same size as the canvas, or other shapes to take up the top-left and bottom-right corners of the svg.
<div id="wrapper">
<div id="gameZone">
<div id="background">
<svg id="svgRoot" width="700" height="700">
<rect width="100%" height="100%" stroke="none" visibility="hidden" pointer-events="none" />
<circle cx="355" cy="600" r="10" id="ball" />
<rect id="pad" height="15" width="150" x="280" y="670" rx="10" ry="20"/>
</svg>
</div>
</div>
</div>

Resources