Setting property of SVG elements from internal script - svg

It's possible to set the property of the elements of SVG direcly from the script?
For example
<svg width="100px" height="100px" version="1.1" onload="setValues()" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">
// <![CDATA[
function setValues() {
//Set cx || cy || whatever of circle
// Set property of rect
}
// ]]>
</script>
<circle id="circleId" cx="50" cy="50" r="45" fill="green" />
<rect id="rectId" height="40" width="400" y="0" x="170" style="fill:#ffffff" />
</svg>

Sure, setAttribute will do that.
<svg width="100px" height="100px" version="1.1" onload="setValues()" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">
// <![CDATA[
function setValues() {
// Set property of circle
document.getElementById("circleId").setAttribute('cx', '20');
// Set property of rect
document.getElementById("rectId").setAttribute('x', '10');
document.getElementById("rectId").setAttribute('style', 'fill:red');
}
// ]]>
</script>
<circle id="circleId" cx="50" cy="50" r="45" fill="green" />
<rect id="rectId" height="40" width="400" y="0" x="170" style="fill:#ffffff" />
</svg>

Related

SVG <use> ignores Gradient styling

I have a svg file that does not render gradient in the <use> tag. Why is it behaving differently, and how can I fix it?
SVG File:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100"
style="stroke:#000000;stroke-width:2"
xml:space="preserve"
id="pb_svg_1">
<rect width="50" height="50" style="fill: url(#lg1)"/>
<defs>
<linearGradient id="lg1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(88,88,88);stop-opacity:1"></stop>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"></stop>
</linearGradient>
</defs>
</svg>
These are 3 methods I render the svg. 2 work but the one I need does not:
<!-- Does NOT include gradient style -->
<svg width="100" height="100">
<use href="12.svg#pb_svg_1" width="100" height="100"/>
</svg>
<!-- Gradient style works! -->
<div>
<object data="12.svg" width="100" height="100"></object>
</div>
<!-- Gradient style works! -->
<div style="width: 100px;height: 100px">
<embed src="12.svg"/>
</div>
I expect the use element to render the file as it does when the svg is on the same page.
EDIT: It does work in firefox and does not work in chrome and edge
Workaround: define gadients in an inlined svg
Move the gradient <defs> to an inlined hidden <svg>.
It's important to hide this svg via zero width and height properties like width:0; height:0;position:absolute;.
display:none or visibility:hidden will remove/disable gradients, clip paths etc.
<!-- HTML svg use instance -->
<svg width="100" height="100" viewBox="0 0 100 100">
<use href="#pb_svg_1" style="fill: url(#lg1); stroke:#000000;stroke-width:2 "/>
</svg>
<!-- Inline svg: hidden gradient definition -->
<svg style="width:0; height:0; position:absolute;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
<defs>
<linearGradient id="lg1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(88,88,88);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
</defs>
</svg>
<!-- External svg: 12.svg -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="pb_svg_1" viewBox="0 0 100 100">
<rect x="0" y="0" width="50" height="50" /></symbol>
</svg>
Workaround 2: inline external use references
If refactoring all svg assets isn't feasible – change your embedding method.
2.1 via fetch
HTML
<!-- HTML svg use instance -->
<svg width="100" height="100" viewBox="0 0 100 100">
<use href="12.svg#pb_svg_1" />
</svg>
Js
inlineExternalUse();
function inlineExternalUse(){
let extSvgs = document.querySelectorAll('use');
if(extSvgs.length){
extSvgs.forEach(function(item, i){
let href = item.getAttribute('href') ? item.getAttribute('href') : item.getAttribute('xlink:href');
// change href to inline reference
let hrefNew = '#'+href.split('#')[1];
item.setAttribute('href', hrefNew);
fetch(href)
.then(response => response.text() )
.then(data => {
//inline ext svg
let parser = new DOMParser();
let svgInline = parser.parseFromString(data, "application/xml").querySelector('svg');
svgInline.setAttribute('aria-hidden', 'true')
svgInline.style.width=0;
svgInline.style.height=0;
svgInline.style.position='absolute';
document.body.appendChild(svgInline);
});
});
}
}
2.2: via native web component
See #Danny '365CSI' Engelman's article "〈load-file〉Web Component, add external content to the DOM" or this answer "How to change the color of an svg element?"

how to make hover effect on pattern?

<!DOCTYPE HTML>
<html lang="ru">
<head>
<title></title>
</head>
<style>
svg{
overflow:hidden;
}
defs:hover{
transform:scale(1.2);
}
</style>
<body style="background:url(http://namonitore.ru/uploads/catalog/znamenitosti/karolina_kurkova__i_devushki_v_bikini_1280.jpg); background-size:cover;">
<svg width="400" height="240">
<polygon points="10 220, 10 10, 280 10,380 220"
style="fill:green; stroke:green; stroke-width:3; opacity="1" />
</svg>
<svg width="400" height="240" style="position:relative; left:-120px;">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="400" height="240">
<image xlink:href="http://www.imagefully.com/wp-content/uploads/2015/07/Sexy-Pause-Girl-Pic.jpg" x="0" y="0" width="400" height="240"/>
</pattern>
</defs>
<polygon points="110 220,10 10,380 10,380 220"
style="fill:url(#img1); stroke:0; stroke-width:0; opacity="1" />
</svg>
</body>
</html>
It is necessary that when you hover over the girls , the effect was as if with background-position.
I do not know much English , but ask longer who.
how to make the zoom effect when you hover over the image of girls ?
If I understand your problem correctly then you should add a class to the polygon that's next to the <defs> element, add a class and use css on that polygon. For
example:
<svg width="400" height="240" style="position:relative; left:-120px;">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="400" height="240">
<image xlink:href="http://www.imagefully.com/wp-content/uploads/2015/07/Sexy-Pause-Girl-Pic.jpg" x="0" y="0" width="400" height="240"/>
</pattern>
</defs>
<polygon class="girls" points="110 220,10 10,380 10,380 220"
style="fill:url(#img1); stroke:0; stroke-width:0; opacity="1" />
</svg>
And then in your CSS instead of:
defs:hover{
transform:scale(1.2);
}
Do this:
polygon.grils:hover{
transform:scale(1.2);
}

How to add text to a rectangle in SVG?

I am trying to put the word "fox" inside this blue rectangle, but it just doesn't happen. What am I doing wrong here?
<html>
<body>
<svg width="400" height="200">
<rect x="50" y="20" width="150" height="150" style="fill:blue;stroke:pink;stroke-width:0;fill-opacity:0.7;stroke-opacity:0.1">
<text fill="#44ffff" font-size="45" font-family="Verdana" x="150" y="96">fox</text>
</svg>
</body>
</html>
As pointed out in my comment, your XML is invalid. The well-formed XML
<svg width="400" height="200">
<rect x="50" y="20" width="150" height="150" style="fill:blue;stroke:pink;stroke-width:0;fill-opacity:0.7;stroke-opacity:0.1" />
<text fill="#44ffff" font-size="45" font-family="Verdana" x="150" y="96">fox</text>
</svg>
works for me.

how to replace an href link in svg with any other id , by clicking on that object

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1 /DTD/svg11-flat-20030114.dtd">
<svg width="640" height="480" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs >
<symbol overflow="visible" id="rect1">
<rect x="142" y="67" width="81" height="67" fill="#003399" stroke="none" stroke- opacity="0" xmlns="http://www.w3.org/2000/svg" />
</symbol>
</defs>
<defs >
<symbol overflow="visible" id="rect2">
<rect x="142" y="67" width="81" height="607" fill="#003399" stroke="none" stroke- opacity="0" xmlns="http://www.w3.org/2000/svg" />
</symbol>
</defs>
<use xlink:href="#rect1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<animateTransform attributeName="transform" begin="0" dur="0.5" fill="freeze" additive="sum" from="-65 7" to="0 0" type="translate" />
<animateTransform attributeName="transform" begin="0.5" dur="0" fill="freeze" additive="sum" from="21 2" to="21 2" type="translate" />
</use>
<circle id="circle" cx="284.5" cy="142.5" r="56.5" fill="#000000" stroke="none" stroke-opacity="0" transform="matrix(1,0,0,1,-1,-34)" xmlns="http://www.w3.org/2000/svg" />
</svg>
this is the code of my svg , it is a sample , i want to change the href id
<use xlink:href="#rect1"
whenever i will chick on the current object
if i will replace the id to
<use xlink:href="#rect2"
it will show another rect, i want to do it at runtime in the browser, on click change the object id at reference
can anyone help me
Here's a quick answer (updated 27/05/13: added <script> tag)
<use id="myImage_ID" xlink:href="#rect1" onclick="myFunc()" .... >
<script> <![CDATA[
function myFunc() {
var svgImg = document.getElementById('myImage_ID')
svgImg.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href" , '#rect2')
}
]]> </script>

SVG: text inside rect

I want to display some text inside SVG rect. Is it possible?
I tried
<svg xmlns="http://www.w3.org/2000/svg">
<g>
<rect x="0" y="0" width="100" height="100" fill="red">
<text x="0" y="10" font-family="Verdana" font-size="55" fill="blue"> Hello </text>
</rect>
</g>
</svg>
But it does not work.
This is not possible. If you want to display text inside a rect element you should put them both in a group with the text element coming after the rect element ( so it appears on top ).
<svg xmlns="http://www.w3.org/2000/svg">
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="0" y="50" font-family="Verdana" font-size="35" fill="blue">Hello</text>
</g>
</svg>
Programmatically using D3:
body = d3.select('body')
svg = body.append('svg').attr('height', 600).attr('width', 200)
rect = svg.append('rect').transition().duration(500).attr('width', 150)
.attr('height', 100)
.attr('x', 40)
.attr('y', 100)
.style('fill', 'white')
.attr('stroke', 'black')
text = svg.append('text').text('This is some information about whatever')
.attr('x', 50)
.attr('y', 150)
.attr('fill', 'black')
You can use foreignobject for more control and placing rich HTML content over rect or circle
<svg width="250" height="250" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="250" height="250" fill="aquamarine" />
<foreignobject x="0" y="0" width="250" height="250">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>Here is a long text that runs more than one line and works as a paragraph</div>
<br />
<div>This is <u>UNDER LINE</u> one</div>
<br />
<div>This is <b>BOLD</b> one</div>
<br />
<div>This is <i>Italic</i> one</div>
</body>
</foreignobject>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(145,200,103);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(132,168,86);stop-opacity:1" />
</linearGradient>
</defs>
<rect width="220" height="30" class="GradientBorder" fill="url(#grad1)" />
<text x="60" y="20" font-family="Calibri" font-size="20" fill="white" >My Code , Your Achivement....... </text>
</g>
</svg>
Programmatically display text over rect using basic Javascript
var svg = document.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'svg')[0];
var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', 20);
text.setAttribute('y', 50);
text.setAttribute('width', 500);
text.style.fill = 'red';
text.style.fontFamily = 'Verdana';
text.style.fontSize = '35';
text.innerHTML = "Some text line";
svg.appendChild(text);
var text2 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text2.setAttribute('x', 20);
text2.setAttribute('y', 100);
text2.setAttribute('width', 500);
text2.style.fill = 'green';
text2.style.fontFamily = 'Calibri';
text2.style.fontSize = '35';
text2.style.fontStyle = 'italic';
text2.innerHTML = "Some italic line";
svg.appendChild(text2);
var text3 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text3.setAttribute('x', 20);
text3.setAttribute('y', 150);
text3.setAttribute('width', 500);
text3.style.fill = 'green';
text3.style.fontFamily = 'Calibri';
text3.style.fontSize = '35';
text3.style.fontWeight = 700;
text3.innerHTML = "Some bold line";
svg.appendChild(text3);
<svg width="510" height="250" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="510" height="250" fill="aquamarine" />
</svg>

Resources