Relative path in SVG to embed <image> when loaded from HTML [duplicate] - html

This question already has an answer here:
How many levels of recursion does SVG support?
(1 answer)
Closed 1 year ago.
i have created an SVG which has an image embedded.
I did this because i want the descriptions to be scalable.
The problem is, when i load the SVG only in chrome, the image is displayed.
When the svg is embedded in an img tag in the html though, i dont see the image.
When i write the svg code in the html file on the other hand the image is displayed.
I think the problem might be a pathing issue but im not sure as i dont get any errors displayed.
The SVG and IMG are in the same folder.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1189.851"
height="539.932">
<image overflow="visible" width="1190" height="540" href="/pics/mashup/e-55211-10-piww-000.png"
transform="translate(0 -.034) scale(.9999)"/>
<g stroke="#1D1D1B" stroke-width="4.693" stroke-miterlimit="10">
<path fill="#FFF" d="M998.689 395.155l-10.44 21.628-67.39-33.204 10.454-21.633z"/>
<path fill="#FFF" d="M911.808 448.549l-22.247-8.621 26.866-70.699 22.247 8.625zM889.081
449.676h23.832v36.11h-23.832z"/>
<path fill="#FFF" d="M920.424 447.646c-2.273 10.825-12.828 17.741-23.553 15.44-10.729-2.301-17.576-12.942-
15.299-23.79 2.283-10.839 12.828-17.75 23.563-15.45 10.715 2.305 17.572 12.952 15.289 23.8zM1012.159
414.767c-4.812 9.959-16.71 14.093-26.559 9.24-9.863-4.854-13.955-16.857-9.148-26.825 4.804-9.959 16.696-
14.089 26.555-9.239 9.858 4.857 13.951 16.861 9.152 26.824zM946.415 380.806c-3.928 10.345-15.413 15.514-
25.66 11.55-10.229-3.969-15.34-15.577-11.417-25.917 3.933-10.34 15.422-15.514 25.656-11.545 10.248 3.968
15.362 15.564 11.421 25.912z"/>
<path fill="none" stroke-linecap="round" d="M980.243 420.437c-6.976 7.153-6.77 18.754.453 25.931M1009.065
446.372c6.972-7.159 6.774-18.75-.444-25.94"/>
</g>
I tried both and they dont work when loaded from an img tag, but do work when opened in browser or inspecting the element:
href="/pics/mashup/e-55211-10-piww-000.png"
href="e-55211-10-piww-000.png"
Thats how i want it to work.
<li class="c-linkedarea" data-content="img2 img" data-display="flex">
<img src="/pics/mashup/e-55211-10-piww-000.svg" alt="Microwall VPN Funktionsgrafik">
</li>
Thanks in advance

The solution to your question has been perfectly addressed by Erik Dahlström in his post here
Here is what CSS tricks has to say about it:
If “inline” SVG just isn’t your jam (remember it does have some legit drawbacks like being hard to cache), you can link to an SVG file and retain the ability to affect its parts with CSS by using .
Basically, you need to put your svg source inside the html <object> element like below:
<object data="pathToYourSVG.svg" type="image/svg+xml">
<img src="backUpImgFileIfSVGDoesNotWork.jpg" />
</object>

Related

Why my svg file code not showing anything in web browser [duplicate]

This question already has an answer here:
How many levels of recursion does SVG support?
(1 answer)
Closed 5 months ago.
<svg viewBox="0 0 200 187" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<mask id="mask0" mask-type="alpha">
<path d="M190.312 36.4879C206.582 62.1187 201.309 102.826 182.328 134.186C163.346 165.547
130.807 187.559 100.226 186.353C69.6454 185.297 41.0228 161.023 21.7403 129.362C2.45775
97.8511 -7.48481 59.1033 6.67581 34.5279C20.9871 10.1032 59.7028 -0.149132 97.9666
0.00163737C136.23 0.303176 174.193 10.857 190.312 36.4879Z"/>
</mask>
<g mask="url(#mask0)">
<path d="M190.312 36.4879C206.582 62.1187 201.309 102.826 182.328 134.186C163.346
165.547 130.807 187.559 100.226 186.353C69.6454 185.297 41.0228 161.023 21.7403
129.362C2.45775 97.8511 -7.48481 59.1033 6.67581 34.5279C20.9871 10.1032 59.7028
-0.149132 97.9666 0.00163737C136.23 0.303176 174.193 10.857 190.312 36.4879Z"/>
<image class="home_blob-img" href="assets/img/perfil.png"/>
</g></svg>
i use this code to show a blob shape in my webpage and insert an image as blob background
Using to embed SVG like this:
<img src="my-file.svg" />
Or using CSS background image like this:
#id {
background-image: url(image.svg);}
These are by far the best choice for static graphics, but could result in missing fonts.
Why?
and background image are not allowed to access to externals links due to security concerns and in this case, the font #import URL is inaccessible, resulting in missing fonts or the fonts being rendered using Times New Roman.

Most efficient way to add inline SVG?

I have a webpage with lots of SVG icons that will be in the HTML. Rather than include them as an IMG tag and possibly slow the page with those HTTP requests, I'm placing the SVG code like this:
<svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" viewBox="0 0 9 9"><path fill="#C5C2BD" fill-rule="nonzero" d="M4.5 3.435L1.286.22A...LOTS OF CODE HERE..."/></svg>
Note: where it says "lots of code here", there is a huge string of numbers/letters that make up the path for this SVG.
The issue this creates is it's very ugly when not easily maintainable in the HTML (to the point where my editor bogs own because these SVG strings are so long).
Is there a cleaner, simpler way to include these SVG icons in my HTML while still eliminating the extra HTTP requests?
Thanks for your time.
The most proven way is to collect all the icons SVG in one file - the sprite SVG
Creating a Sprite and connecting it to HTML
The action plan is as follows:
Creating a Sprite
Connecting it to HTML
Calling SVG images from the sprite
Styling icons
Creating a Sprite
The main task of the sprite is to be a repository for icons that before the call to a specific place HTML pages should be invisible.
To do this,the code for each icon is wrapped with <symbol id =" .. "> ... </ symbol> tags with a unique identifier, which will be followed by the <use>
Template Sprite:
<div id="container">
<svg version="1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 126 126" >
<symbol id="picasa">
<path d="M113.5 57.... 72.8z" />
</symbol>
<symbol id="wordpress" viewBox="0 0 126 126">
<path stroke ="black" d="M113.5 57.7l-8.5-11.4 .. 86.1 62.9z"/>
</symbol>
<symbol id="twitter">
<path d="M113.5 57.6l-8.5-11.4.... 7.4-2.4V85.4z"/>
</symbol>
<symbol id="apple">
<path d="M113.5 57.7l-8.5-11.4... 78.5 78.7 82z"/>
</symbol>
</div>
As you can see, all <path> attributes are removed for later styling of icons from an external CSS file.
Adding a sprite file to HTML
There are several ways to add SVG files to HTML, but the most reliable way is to add it using the <object>
<object type="image/svg+xml" data="Sprite.svg" width="200" height="200">
Your browser does not support SVG
</object>
Adding icons from the sprite
<div id="container">
<svg viewBox="0 0 126 126" >
<use xlink:href="#apple"></use>
</svg>
</div>
The viewBox attributes should be like thesvg icon or change the scaling inside HTML if necessary.
Icons as links
For this, in SVG, unlike HTML, its own form of record
<svg viewBox="0 0 126 126" >
<a xlink:href="https://www.apple.com/ru/"><use xlink:href="#apple"></use></a>
</svg>
Styling icons
When using the <use> command, the icon falls into the shadow DOM and its attributes behave strangely, - there is an icon of the icon, but it can not be controlled from the outside.
In addition, the icon attributes for example: style = "fill: gray; stroke: crimson;" have the highest priority. Therefore, we deleted these attributes. see the example of the sprite above.
To solve the problem of inheritance of parental properties by objects in shadow DOM, you must use forced inheritance
svg path{
fill:inherit;
stroke:inherit;
}
and then to the icons you can already apply CSS rules from the external table
svg path:hover{fill:yellow;}
#picasa{fill:black;}
#apple{fill:purple;}
#twitter{fill:black;}
#wordpress{fill:blue;}
If you go for the first time along this path, then inevitably there will be many questions.
Ask, do not be shy.
All sooner or later it turned out to be done and customized sprite.
The main recommendation is to do everything yourself manually for the first time, to understand how it is arranged, and then you can already openly use special utilities to automatically create sprites.
You should convert all your .svg files to one font file, here is how:
How to convert .svg files to a font?

How to use SVG clipPathUnits="objectBoundingBox"

I'm trying to use an SVG to mask an image.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width=500 height=300>
<defs>
<clipPath id="clip">
<path d="M2.16,1.363h23.699c13.739,0,24.899,10.74,24.899,23.999s-11.16...
<img width="500" style="clip-path: url(#clip);-webkit-clip-path: url(#clip);" />
It works but I want the clipPath size to match the media. In Chrome I can control the size of the clipPath with CSS but in FF the clipPath stays small. In Safari with one asset nothing appears and with another it appears off-center.
I've read other questions that talk about using clipPathUnits:
<clipPath id="clip" clipPathUnits="objectBoundingBox">
But I cannot get this to work at all. Apparently it expects the paths units to be decimals... but my shape is too complicated to write by hand and I don't know of any design software that supports that format.
Update
Following Robert's comments, I tried adding a CSS transform to the clipPath to "translate" the units...
#clip {
-webkit-transform:scale(0.004195862879,0.005554321262);
transform:scale(0.004195862879,0.005554321262);
}
This allowed objectBoundingBox to work as expected in Chrome. But still no luck with Safari or FF. It appears that Safari still renders the clipPath outside the the element to be clipped... making it invisible. FF developer tools make it less clear where it's placing the clipPath.
Run into this problem right now and found the solution. Thanks #RobertLongson for mentioning that when you applying clipPathUnits="objectBoundingBox", you should be sure that all of your coordinates are between 0 and 1. It means, that if you have, for example, a circle
<svg viewBox="0 0 20 20">
<defs>
<clipPath id="clip">
<circle cx="10" cy="10" r="10" />
</clipPath>
</defs>
</svg>
then with clipPathUnits="objectBoundingBox" it should looks like this:
<svg>
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5" />
</clipPath>
</defs>
</svg>
In case of complex paths, I found one solution. All you need is an application for vector images editing. For Linux it could be Gravit Designer (I used it and it worked).
Create new file of size 1x1
Open you svg that contains your complex path without clipPath tag. If you don't have such source, then you can simply create new text file, paste your <path .../> into <svg>...</svg> and save it with *.svg extension, and then open it in your application (Gravit Designer).
Copy your complex path from opened svg and paste it into created new file (1x1).
Turn off "Preserve aspect ratio" (or something simillar) function if it enabled
Set this parameters for your complex path: Width: 1px, Height: 1px, Top: 0px, Left: 0px.
Save this 1x1 file as svg.
Open this svg file in text editor and copy the value of d attribute.
Now you have your complex path in relative coordinates. Set it into you clip
...
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="/* your copied value */" />
</clipPath>
...
Done! Now you can enjoy your responsive clip path without any additional transformations or other workarounds.
I know, it looks too complicated, but it really will be done in approximately 2 minutes (if you have vector image editing software installed).
Hope this helps someone despite of question was asked 1.5 years ago :)
I was using Adobe Illustrator to try and shrink my vectors down to 1px by 1px, and it wasn't capturing all of the coordinates correctly. I instead found this awesome online tool that will convert SVG path coordinates to CSS clip-path friendly coordinates relative to a "1" unit without needing a vector editing program. The quality is much better than Illustrator and easier to use. 🙌
https://yoksel.github.io/relative-clip-path/
I got a similar problem, I solved it like this:
I transfer the svg file to figma (drag and drop)
I align to a square 100 by 100 (without preserving the sides)
export the file as svg
I upload the file to the service https://betravis.github.io/shape-tools/path-to-polygon/ (not advertising, you can use something else)
I get a clean polygon as a percentage, which can be used in clip-path;
example:
.elem-to-path{
clip-path: polygon(89.758% 99.457%, 67.178% 99.862%, 39.660% 99.621%, 7.748% 98.475%, 5.924% 98.004%, 5.742% 97.859%, 4.348% 92.036%, 1.807% 80.831%, 0.174% 36.869%, 1.052% 1.541%, 1.301% 1.012%, 2.237% 0.790%, 62.832% 0.559%, 78.860% 0.810%, 88.832% 0.810%, 96.913% 1.195%, 98.441% 3.283%, 99.616% 24.932%, 98.813% 86.202%, 96.703% 95.116%, 89.758% 99.457%)}

SVG Pattern Doesn't Show on Page

I am completely clueless, what is going wrong with my svg pattern. I defined it in the def section of the svg and then tried to reference it. But it doesn't show up once I include the svg in an img-tag. If I open it on itself in the browser everything is good though.
See the following examples:
http://kijani.co/img/sketch/index.html
http://kijani.co/img/sketch/livingroom.svg
And my code:
<defs>
<pattern id="paper" patternUnits="userSpaceOnUse" width="200" height="200">
<image xlink:href="http://kijani.co/img/pattern/paper.jpg" width="200" height="200"/>
</pattern>
</defs>
<g id="background">
<path id="paper" fill="url(#paper)" d="..."/>
</g>
This might be a really stupid question, but I am fairly new to svg and couldn't find a solution anywhere so far.
This is svg's referencing mode probrem.
Using img element to display svg image is restrected for refering outer resources.
So you should use object element to display svg image, or embed pattern image into svg by data scheme format.

Selenium: SVG element embedded into Object tag is not been identified by Selenium IDE or xPath?

I have an html segment like this
<div id="imageholder>
<object data="1.svg" width="100%" height="100%" type="image/svg+xml">
</object>
</div>.
When i see the inspect element in Firefox/firebug i can't see the SVG file structure,
but in Chrome i am able to see the svg file structure like below:
<div id="imageholder>
<object data="1.svg" width="100%" height="100%" type="image/svg+xml">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-dasharray="none"
shape-rendering="auto" font-family="'Dialog'" width="4800">
<desc>widthmm=90.48768097536195 heightmm=49.38127063754128</desc>
<g>
<g>....</g>
</g>
However, i am not able to locate svg tag or any g element through X-path. I tried with
//div[contains(#id='imageholder')]
then i get the element correctly.
//div[contains(#id='imageholder')/object]
also returns element correctly. But
//div[contains(#id='imageholder')/object/svg]
fails.
My requirement is: I need to click on several g elements of SVG image, but i am not able to reach it.
Your help will be appreciated.
Thanks
Some more details added on:[Dec 8,2011]
driver.findElement(By.xpath("//div[#id='imageholder']/object"));//This worked correctly
driver.findElement(By.xpath("//div[#id='imageholder']/object/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg']"));//did not work
I also tried all the possible combination XPath - Find elements by attribute namespace given on this link but could not succeed.
Thanks
For more details, please find the sample code.
Sample.html
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9;chrome=IE8">
<body>
<div id="imageholder"><object data="1.svg" width="100%" height="100%" type="image/svg+xml"></object></div>
</body>
</html>
1.svg
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg stroke-dasharray="none" shape-rendering="auto" xmlns="http://www.w3.org/2000/svg" font-family="&apos;Dialog&apos;"
width="4800" text-rendering="auto" fill-opacity="1" contentScriptType="text/ecmascript" color-interpolation="auto"
color-rendering="auto" preserveAspectRatio="xMidYMid meet" font-size="12" viewBox="0 0 4800 2619" fill="black"
xmlns:xlink="http://www.w3.org/1999/xlink" stroke="black" image-rendering="auto" stroke-miterlimit="10"
zoomAndPan="magnify" version="1.0" stroke-linecap="square" stroke-linejoin="miter" contentStyleType="text/css"
font-style="normal" height="2619" stroke-width="1" stroke-dashoffset="0" font-weight="normal" stroke-opacity="1"
>
<g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;">
<circle cx="6cm" cy="2cm" r="100" style="fill:red;"
transform="translate(0,50)"/>
<circle cx="6cm" cy="2cm" r="100" style="fill:blue;"
transform="translate(70,150)"/>
<circle cx="6cm" cy="2cm" r="100" style="fill:green;"
transform="translate(-70,150)"/>
</g>
</svg>
Please click on sample.html once you save the files.
//div[contains(#id='imageholder')/object/svg fails because you didn't tell the processor that the namespace of the svg element is not the same as the other. See the xmlns="http://www.w3.org/2000/svg".
You can write : //div[contains(#id,'imageholder')]/object/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'].
EDIT (after reading your update) :
Problem can be : in your original html file, you have a link to the svg file in your object element.
Even if your browser incorporate the svg file in the dom, the XPath expression seems to act on the original file itself (with the href). Sorry, but I'm not aware of those kind of use cases for XPath, and can't tell you more.
Got some work around to get SVG embedded document. It doesn't seems to be possible via WebElement. But through JavaScriptExecutor, we can get the complete DOM reference and through standard DOM pattern it is possible.
Like: We can do->docuemnt.getElementsByTagName('OBJECT').contentDocument. This will give the complete SVG DOM reference.
The link below doesn't seem to be the direct answer of it, but possibility of Sel2.0 can be seen through this.
Selenium: Can I set any of the attribute value of a WebElement in Selenium?
Might be helpful for all:-)
Thanks
Switch to the default frame before trying to access the SVG tag, i.e frame(0).
Tried many XPath solutions nothing worked, but switching to frame worked as a charm, its treating SVG as a frame here.
System.setProperty("webdriver.gecko.driver", "C:\\Users\\Administrator\\Downloads\\geckodriver-v0.18.0-win64\\geckodriver.exe");
WebDriver d = new FirefoxDriver();
d.navigate().to("file:///C:/Users/Administrator/Desktop/sample/svg.html");
Thread.sleep(2000);
d.switchTo().frame(0);
Actions builder = new Actions(d);
WebElement svgObject = d.findElement(By.xpath("(//*[name()='svg']/*[name()='g']/*[name()='circle'])[2]"));
//"style" here prints the colour of the second circle in the svg tag. ie( blue circle)
System.out.println(svgObject.getAttribute("style"));
System.out.println(svgObject.getAttribute("transform"));
System.out.println(svgObject.getAttribute("cx"));
System.out.println(svgObject.getAttribute("cy"));
System.out.println(svgObject.getAttribute("r"));
builder.moveToElement(svgObject).click();