I have a razor component and I want to add an SVG to it.
Would It be best to create a component for each SVG so that I can re-use it pretty easily or would it be better to just include the SVG into the blazor page?
Those are just the two ways I thought that it could be done, whats the best way to go about this and how can I implement it?
Haven't found any rescources, so I wasn't able to try anything.
I gave it try, as far as I can see the Blazor Component model works perfectly well with Svg:
SvgHolder.razor
<svg width="100" height="100">
#ChildContent
</svg>
#code {
[Parameter]
public RenderFragment ChildContent { get; set; }
}
SvgSample.razor
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
#code {
}
TestPage.razor
<SvgHolder >
<SvgSample />
</SvgHolder>
One way that I found to do it:
Add the files inside wwwroot:
then just add it to the HTML page:
<img src="Images/scissors.svg" />
EDIT:
This works if you don't need to edit the image with css.
Read #J-Ho comments.
Related
I'm using the yFiles for HTML chart library, which supports rendering nodes using SVG templates. According to the documentation, this is done by embedding a special <script> tag in the main HTML file with somewhat SVG elements in it (without the enclosing <svg> container).
<script type="text/yfiles-template">
<g id="expand_icon" transform="translate(21 6)">
<polygon stroke="#FFFFFF" stroke-width="3" fill="none"
points="6,17 6,12 1,12 1,6 6,6 6,1 12,1 12,6 17,6 17,12 12,12 12,17"/>
</g>
</script>
The problem is that putting all my templates in the main HTML file is messy, and I would rather split them into several external SVG files. However, if I simply copy the <script>'s contents into an external file and try changing the script tag like this:
<script type="text/yfiles-template" src="images/nodeTemplates.svg"></script>
doesn't seem to work. No error is displayed, but my templates aren't shown.
I can't find anything else in the docs about it, and it's entirely possible that it's hardcoded to look for it in the main HTML, but I was wondering if anyone managed to get it to read the templates from an external file.
I suggest you use the StringTemplateNodeStyle where you just pass the svg snippet as a string to the style. You can then use your own loading mechanism to retrieve the snippets.
Note that if you don't need all the data binding features of the TemplateNodeStyle, but just want to dynamically include an svg file as an image, you can just as well use the ImageNodeStyle and point it directly to your SVG resource. Alternatively implementing your own style as shown in the custom style tutorial is also a very feasible and flexible solution.
The node has and image property you can use for a valid .svg file aka:
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
The above will give you the ability to put each svg in a different .svg file.
My research came up with a several ways to insert SVG images inside an html page.
Using <img> is the most simple one but lack of ability as coloring the icons, which is my main need. So, I've read about using <object> but this still doesn't let me styling it using css fill command.
Putting the bulk of <svg> data is also non acceptable since I want to use the images as a refernced images.
I've also read about jQuery solution but I use angularJS.
So, I've read a lot about the ability of SVG Icons, and how better they are rather than the old PNG-Sprite or the IconFonts hype. but unfortunatelly, I cant find any good reference for using it. Can anyone help me here?
tried this already, this doesn't work:
html:
<object data="your.svg" type="image/svg+xml" id="myImage"></object>
css:
#myImage {
fill: #fff;
}
For <img> manupulation, read How to change color of SVG image using CSS (jQuery SVG image replacement)?
For embedding you have 3 choices:-
<object id="myObj" data="image.svg" width="200px" height="200px" type="image/svg+xml"></object>
<embed id="myEmb" src="image.svg" type="image/svg+xml" width="200px" height="200px" ></embed>
<iframe id="myIfr" src="image.svg" width="200" height="200" style="border:0" ></iframe>
Say the image.svg contains this circle in red: <circle id="redcircle" cx="100" cy="100" r="50" fill="transparent" stroke="red" stroke-width="3""/>
To manipulate this color, try this function: ColObj('myObj','blue'), ColObj('myEmb','blue') or ColObj('myIfr','blue')
function getSubDocument(embedding_element)
{
if (embedding_element.contentDocument)
{
return embedding_element.contentDocument;
}
else
{
var subdoc = null;
try {
subdoc = embedding_element.getSVGDocument();
} catch(e) {}
return subdoc;
}
}
function ColObj(elem, color)
{
var elms = document.getElementById(elem);
var subdoc = getSubDocument(elms);
if (subdoc)
subdoc.getElementById("redcircle").setAttribute("stroke", color);
}
This guide from CSS tricks is the best reference I've found so far.
Your options are, unfortunately, pretty limited to use CSS to style an SVG that's not inlined. It involves either embedding the styles inside the SVG file or linking to the stylesheet from within the SVG itself.
Both techniques are discussed in the CSS tricks guide.
Here's a JSFiddle demonstrating the linked CSS technique.
Here's how it works:
Link to the stylesheet from within the CSS and add classes to the individual paths:
<?xml-stylesheet type="text/css" href="mysvg.css"?>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
<path class="demo-content" d="M11.31 44.5l12.69-12.3 12.691 12.3 7.809-8.2-12.69-12.3 12.69-12.3-7.809-8.2-12.691 12.3-12.69-12.3-7.81 8.2 12.691 12.3-12.691 12.3 7.81 8.2z" fill="rgb(98.34%, 88.24%, 32.2%)"/>
<path class="demo-border" d="M11.31 44.5l12.69-12.3 12.691 12.3 7.809-8.2-12.69-12.3 12.69-12.3-7.809-8.2-12.691 12.3-12.69-12.3-7.81 8.2 12.691 12.3-12.691 12.3 7.81 8.2z" stroke="#ccc" stroke-linecap="square" fill="none"/>
</svg>
Create the css file, in this case mysvg.css:
.demo-content {
fill: #FF0000;
}
If you're trying to conditionally style the SVG, though, you may have no chose other than embed it.
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.
I have an html file that uses inline svg. I use this so I can add classes to my svg and style them with CSS. The following snippet works:
<div>
<svg class="icon" viewbox="0 0 512 512">
<path d=" ... "/>
</svg>
</div>
Howeever, the tag can be quite long if the svg is complex. I'm currently using this svg in 3 different locations, and everytime I need to copy paste the entire path. It would be better if I could define the path only 1 time, preferabvly in a css class like this:
<div>
<svg class="icon" viewbox="0 0 512 512">
<path class="compleximage"/>
</svg>
</div>
.compleximage
{
d: ... ;
}
But this doesn't seem to work. Maybe I'm getting it wrong syntactically, or maybe it can't be done this way. If so, are there ways other to prevent having to copy/paste the svg in my html files? I'm trying to follow the "0,1 or infinite" design pattern, and copy/pasting code 3 times break that.
You can use the use tag to display the path in more than one place. Just give the path an id attribute and then refer to that in the xlink:href of the <use> element.
Something like
<defs>
<path id="image1" d="..." />
</defs>
<use x="20" y="10" xlink:href="#image1" />
<use x="50" y="50" xlink:href="#image1" />
etc.
In HTML5 you can do it.
Please try this:
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
On the other hand, you can create your own SVG and get it via <img src="" />.
Sample below:
<img class="papa" src="http://s.cdpn.io/3/kiwi.svg">
Reference here:
(1) http://css-tricks.com/using-svg/
Another reference here how to change it via css:
(2) http://codepen.io/chriscoyier/pen/evcBu
You cannot set svg attributes using CSS. You can only set styles like stroke, fill, etc.
The only way would be to use javascript to set those paths dynamically. I would recommend jQuery.
this link should be helpful for using jQuery to modify svg files.
Modify a svg file using jQuery
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="'Dialog'"
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();