Show multiple SVG layers from HTML document - javascript

I have an SVG file containing 3 vector shapes:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="800px" height="1500px" viewBox="0 0 1500 1500" enable-background="new 0 0 1500 1500" xml:space="preserve">
<svg:style xmlns:svg="http://www.w3.org/2000/svg" type="text/css">
g { display: none; }
g:target { display: block; }
</svg:style>
<g id="svgRed">
<rect x="301" y="344" fill="#DB1919" stroke="#000000" stroke-width="10" stroke-miterlimit="10" width="286" height="314"/>
</g>
<g id="svgGreen">
<circle fill="#1AD84B" cx="692.143" cy="1007.381" r="180.953"/>
</g>
<g id="svgBlue">
<path fill="#1A7ED8" d="M1271,1052c0,1.657-1.343,3-3,3h-251c-1.657,0-3-1.343-3-3V347c0-1.657,1.343-3,3-3h251 c1.657,0,3,1.343,3,3V1052z"/>
</g>
</svg>
As you see, I have each shape in a separate group. I've set all groups to display:none unless they are targeted. Now I can show the blue shape in an HTML document like so:
<object data="test.svg#svgBlue" type="image/svg+xml" width="600" height="860">
My question is, what if I want to show two of the shapes? I can't seem to target more than one shape in the HTML.
I'll be using javascript alongside this, so that is also acceptable to use.

Firstly, you must insert the SVG inline in your HTML5 Document. The object is not accessible via local javascript. Then it's possible to show/hide and change all elements via the DOM. You can load inline svg as xml using XMLHttpRequest
and then have the response fill the innerHTML of a DIV.
Try the files below. Once it is loaded you can use the buttons to toggle display.
Assume you have an svg file(my.svg)
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1500 1500">
<g id="svgRed" display="inline">
<rect x="301" y="344" fill="#DB1919" stroke="#000000" stroke-width="10" stroke-miterlimit="10" width="286" height="314"/>
</g>
<g id="svgGreen" display="inline">
<circle fill="#1AD84B" cx="692.143" cy="1007.381" r="180.953"/>
</g>
<g id="svgBlue" display="inline">
<path fill="#1A7ED8" d="M1271,1052c0,1.657-1.343,3-3,3h-251c-1.657,0-3-1.343-3-3V347c0-1.657,1.343-3,3-3h251 c1.657,0,3,1.343,3,3V1052z"/>
</g>
</svg>
And your HTML5 document is as below:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<center>
<div id="svgInlineDiv" style='background-color:lightgreen;width:300px;height:300px;'></div>
<button onClick=toggleDisplay(svgRed)>toggle red</button>
<button onClick=toggleDisplay(svgBlue)>toggle blue</button>
<button onClick=toggleDisplay(svgGreen)>toggle green</button>
</center>
<script id=myScript>
function toggleDisplay(me)
{
if(me.getAttribute("display")=="inline")
me.setAttribute("display","none")
else
me.setAttribute("display","inline")
}
</script>
<script>
document.addEventListener("onload",inlineSVG(),false)
function inlineSVG()
{
var SVGFile="my.svg"
var loadXML = new XMLHttpRequest;
function handler(){
if(loadXML.readyState == 4 && loadXML.status == 200)
svgInlineDiv.innerHTML=loadXML.responseText
}
if (loadXML != null){
loadXML.open("GET", SVGFile, true);
loadXML.onreadystatechange = handler;
loadXML.send();
}
}
</script>
</body>
</html>

Related

Insert current timestamp inside svg

I am trying to insert a current timestamp inside an svg image:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="618px" height="100px" viewBox="0 0 618 100" style="enable-background:new 0 0 618 100;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;}
.st1{font-family:'Arial-BoldMT';}
.st2{font-size:36;}
</style>
<rect x="3" y="30" class="st0" width="611" height="100"/>
<text transform="matrix(1 0 0 1 263.4561 55.7754)" class="st1 st2">
</text>
<script type="text/javascript"><![CDATA[
var text = document.getElementByTagName('text');
var time = new Date();
var textnode = document.createTextNode(time);
text.appendChild(textnode);
]]></script>
</svg>
https://jsfiddle.net/km87r2ug/
Any ideas why this won't work?
If you looked in your browser's error console you'd see that getElementByTagName does not exist. The function you want is getElementsByTagName which returns more than one element so I took the first one...
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="618px" height="100px" viewBox="0 0 618 100" style="enable-background:new 0 0 618 100;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;}
.st1{font-family:'Arial-BoldMT';}
.st2{font-size:36;}
</style>
<rect x="3" y="30" class="st0" width="611" height="100"/>
<text transform="matrix(1 0 0 1 263.4561 55.7754)" class="st1 st2">
</text>
<script type="text/javascript"><![CDATA[
var text = document.getElementsByTagName('text')[0];
var time = new Date();
var textnode = document.createTextNode(time);
text.appendChild(textnode);
]]></script>
</svg>
There is no document.getElementByTagName method. Try using document.querySelector instead.

Edit html attribute of another page

I have code which is work for edit attributes of .svg file in same page
function changeInnerColor() {
var y = document.getElementsByClassName("inner");
var j;
for (j in y){
y[j].setAttribute("fill","#494949");
console.log(y[j]);
}
}
function changeOuterColor(){
var x = document.getElementsByClassName("outer");
var i;
for (i in x){
x[i].setAttribute("fill","#ff0");
console.log(x[i]);
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="130px" height="130px" viewBox="0 0 130 130" enable-background="new 0 0 130 130" xml:space="preserve">
<g>
<g id="Shape_1_copy_3_18_">
<ellipse fill="#0481D9" class="outer" cx="65" cy="65" rx="64" ry="64.018"/>
</g>
<g id="Shape_8">
<path fill="#FFFFFF" class="inner" d="M70.139,46.547h8.828V35.615h-8.828c-7.303,0-13.24,6.436-13.24,14.346v5.517H48.07v10.967h8.828v26.552
h11.033V66.444h11.035V55.478H67.932v-5.621C67.932,47.963,69.102,46.547,70.139,46.547z"/>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="130px" height="130px" viewBox="0 0 130 130" enable-background="new 0 0 130 130" xml:space="preserve">
<g>
<g id="Shape_1_copy_3_22_">
<ellipse fill="#EE3849" class="outer" cx="65" cy="65" rx="64" ry="64.017"/>
</g>
<g id="Shape_153">
<path fill="#FFFFFF" class="inner" d="M74.044,52.203H63.407c-2.937,0-5.318,2.378-5.318,5.318c0,2.934,2.382,5.318,5.318,5.318h10.637
c2.46,0,5.318,4.061,5.318,9.307c0,5.131-4.771,9.307-10.637,9.307h-5.318c-5.864,0-10.637-4.772-10.637-10.637V44.225
c0-2.94-2.381-5.318-5.318-5.318c-2.937,0-5.318,2.378-5.318,5.318v26.592c0,11.729,9.544,21.273,21.273,21.273h5.318
c11.73,0,21.273-8.948,21.273-19.943C89.999,61.146,82.842,52.203,74.044,52.203z"/>
</g>
</g>
</svg>
<input id="button1" type="button" value="Change Inner Color" onclick="changeInnerColor()"/>
<input id="button2" type="button" value="Change Outer Color" onclick="changeOuterColor()"/>
But i need to add that .svg file with img and edit it like
<img scr="facebook.svg">
And i need make changes into facebook.svg page as per user action.
THANKS.
Set your image
<img scr="facebook.php?innercolor=FFFFF&outercolor=0481D9" id="myImage">
Create your svg using php
<?php
header('Content-Type: image/svg+xml ');
$innercolor = $GET['innercolor'];
$outercolor = $GET['outercolor'];
?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="130px" height="130px" viewBox="0 0 130 130" enable-background="new 0 0 130 130" xml:space="preserve">
<g>
<g id="Shape_1_copy_3_22_">
<ellipse fill="#<?php echo $innercolor; ?>" class="outer" cx="65" cy="65" rx="64" ry="64.017"/>
</g>
<g id="Shape_153">
<path fill="#<?php echo outercolor; ?>" class="inner" d="M74.044,52.203H63.407c-2.937,0-5.318,2.378-5.318,5.318c0,2.934,2.382,5.318,5.318,5.318h10.637
c2.46,0,5.318,4.061,5.318,9.307c0,5.131-4.771,9.307-10.637,9.307h-5.318c-5.864,0-10.637-4.772-10.637-10.637V44.225
c0-2.94-2.381-5.318-5.318-5.318c-2.937,0-5.318,2.378-5.318,5.318v26.592c0,11.729,9.544,21.273,21.273,21.273h5.318
c11.73,0,21.273-8.948,21.273-19.943C89.999,61.146,82.842,52.203,74.044,52.203z"/>
</g>
Update your image
function changeInnerColor() {
var y = document.getElementsByID("myImage");
y.src = "facebook.php?innercolor=494949&outercolor=0481D9";
}
function changeOuterColor(){
var x = document.getElementsByID("myImage");
x.src = "facebook.php?innercolor=494949&outercolor=ff0";
}
Use the object tag
<object id="img1" type="image/svg+xml" data="img.svg"/>

Added svg image into canvas using fabric.js not visible in firefox

I am adding background svg image to my canvas using fabric.js in my angular.js application, the background is visible perfectly in chrome but not in firefox, I have provided js code and svg.
I am using firefox 47.0.1 on OSX 10.11.5
Why it is not visible in firefox?
Any help will be appreciated.
var image="mysvg.svg";
$window.fabric.Image.fromURL(image, function(oImg) {
oImg.width = width;
oImg.height = height;
oImg.lockMovementX = true;
oImg.lockMovementY = true;
oImg.lockRotation = true;
oImg.lockScalingX = true;
oImg.lockScalingY = true;
oImg.selectable = false;
oImg.selectable = false;
oImg.id = 'bg_image';
canvas.centerObject(oImg)
.add(oImg)
.sendToBack(oImg)
.renderAll();
});
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="mysvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 921.3 921.3" style="enable-background:new 0 0 921.3 921.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#DEDEDE;}
.st1{fill:none;stroke:#000000;stroke-width:0.75;stroke-miterlimit:10;}
</style>
<g id="Jacket_Spine">
<g id="jacket">
<g>
<polygon class="st0" points="719.3,420.1 200.7,420.1 17,471.7 903,471.7 "/>
</g>
</g>
<rect id="Spine_1_" x="17" y="471.8" class="st1" width="887.2" height="11.3"/>
</g>
</svg>
You are hitting a firefox bug wher a svg without specified width and height cannot be drawn on canvas.
You should modify your SVG and add a width and height to it.
Also the code to add the image as background could be made simpler, unless you have some reason to have it in that way.
Here is the firefox BUG just as a reference:
https://bugzilla.mozilla.org/show_bug.cgi?id=700533
Probably the image will not show on internet explorer 11 also.
var image="mysvg.svg";
fabric.Image.fromURL(image, function(oImg) {
canvas.bakgroundImage = oImg;
canvas.renderAll();
});
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="mysvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="922" height="922" viewBox="0 0 921.3 921.3" style="enable-background:new 0 0 921.3 921.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#DEDEDE;}
.st1{fill:none;stroke:#000000;stroke-width:0.75;stroke-miterlimit:10;}
</style>
<g id="Jacket_Spine">
<g id="jacket">
<g>
<polygon class="st0" points="719.3,420.1 200.7,420.1 17,471.7 903,471.7 "/>
</g>
</g>
<rect id="Spine_1_" x="17" y="471.8" class="st1" width="887.2" height="11.3"/>
</g>
</svg>

SVG is accessible when embedded but not when included

I have a map with SVG and I am going to create an Area Map with that. It works well when I embed that SVG file in my HTML page, but not when I include it by
This is my SVG:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="595.28px" height="841.89px" viewBox="0 0 595.28 841.89" enable-background="new 0 0 595.28 841.89" xml:space="preserve">
<g id="Layer_1">
<rect x="106.429" y="86.429" fill="#D32A2A" stroke="#000000" stroke-miterlimit="10" width="311.429" height="194.286"/>
</g>
<g id="Layer_2">
<rect x="127.144" y="261.143" fill="#1F5785" stroke="#000000" stroke-miterlimit="10" width="311.428" height="194.287"/>
</g>
</svg>
And this is my javascript:
$(function(){
$('#Layer_2').click(function() {
alert('Thanks');
});
});
This works well and when I click on blue square, an alert shows. DEMO
But I need to include it like this:
<object data="map.svg" type="image/svg+xml" id="map-id" width="100%" height="100%"></object>
and when I include it, I don't have access to that. DEMO
You right this don't work...
You need for use "live" bind, because when you include it directly it
load in not same time as your script:
$('#Layer_2').live('click', function() {
alert('Thanks');
});
I have found this solutions first for read, second for read
To access svg.contentDocument it must be loaded from the same domain, and it will be null otherwise.
There working DEMO.
for simlify your use svg as inside you must start your code after loading all svg objects:
<object id="mysvg1" data="./test.svg" type="image/svg+xml" width="100%" height="100%"></object>
<object id="mysvg2" data="./test.svg" type="image/svg+xml" width="100%" height="100%"></object>
...
var my_start_function = function(){
// start your code here
}
...
var svg_objects = ['mysvg1','mysvg2'], load_counter = 0;
for (var i in svg_objects) {
document.getElementById(svg_objects[i]).addEventListener("load",function() {
load_counter++;
if (load_counter == svg_objects.length) my_start_function();
}, false);
}
and access to svg elements throught a little function:
var svg_inside = function(svg_id,elem_id) {
return $($(document.getElementById(svg_id.substr(1)).contentDocument).find(elem_id)[0]);
}
...
svg_inside('#mysvg1','#Layer_2').click(function() {
alert('Thanks');
});

Interactive SVG with JavaScript | embed or not embed SVG?

I am trying to change the attribute of a circle in an SVG via javascript. When I have the SVG directly embeded in the HTML file, it works: 'kreis1' is changing color upon clicking a button. But when I have the SVG in an extra file (which I would like to have ultimatly when the SVG will have more than two circles), 'kreis1' doesn't react.
The is my SVG file, two circles:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<circle id="kreis1" fill="#8CC63F" stroke="#000000" cx="53.318" cy="55.5" r="50"/>
<circle id="kreis2" fill="#C44741" stroke="red" cx="138.786" cy="130" r="30" stroke-width="0"
onmouseover="evt.target.setAttribute('stroke-width','10');"
onmouseout="evt.target.setAttribute('stroke-width','0');"/>
</svg>
... and here is my HTML:
<!DOCTYPE html>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<circle id="kreis1" fill="#8CC63F" stroke="#000000" cx="53.318" cy="55.5" r="50"/>
<circle id="kreis2" fill="#C44741" stroke="red" cx="138.786" cy="130" r="30" stroke-width="0"
onmouseover="evt.target.setAttribute('stroke-width','10');"
onmouseout="evt.target.setAttribute('stroke-width','0');"/>
</svg>
<button onclick="getElementById('kreis1').innerHTML=changeColor()">Change!</button>
<object type="image/svg+xml" data="test.svg">
<html>
<head>
<script>
var htmlDocument = document;
function changeColor()
{
document.getElementById("kreis1").setAttribute("fill", "blue");
}
</script>
</head>
</html>
test.svg is a different document to the html document. Fortunately you can get the test.svg document via the contentDocument field on the <object> tag.
<!DOCTYPE html>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<circle id="kreis1" fill="#8CC63F" stroke="#000000" cx="53.318" cy="55.5" r="50"/>
<circle id="kreis2" fill="#C44741" stroke="red" cx="138.786" cy="130" r="30" stroke-width="0"
onmouseover="evt.target.setAttribute('stroke-width','10');"
onmouseout="evt.target.setAttribute('stroke-width','0');"/>
</svg>
<button onclick="getElementById('kreis1').innerHTML=changeColor()">Change!</button>
<object id="object1" type="image/svg+xml" data="test.svg">
<html>
<head>
<script>
var htmlDocument = document;
function changeColor()
{
document.getElementById("object1").contentDocument.getElementById("kreis1").setAttribute("fill", "blue");
}
</script>
</head>
</html>
It's a limitation of browser layout engines. External SVGs can't be styled by CSS. They have to be embedded in the HTML directly. JavaScript does permit interaction via the object tag per Robert's answer.
If you'd like to go down the embedding route (in my opinion it is more flexible) I've developed a script to automate this embedding, I've got a couple of hours so I'll bundle it up into something reusable this morning and update the question when it's done.
EDIT: Here's the embedding plugin, with docs: http://sakurasvg.appsondemand.com.au/

Categories