I've got 3 files: test.html, test.js and test.svg
I'm trying to call the different files into HTML but the file svg don't work
test.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Using SVG as an object</title>
<link href="index.css" rel="stylesheet" />
</head>
<body>
<h1>Test</h1>
<script type="text/javascript" src="test.js"></script>
<object data="test.svg" width="300" height="300"> </object> <!-- Not working -->
<input type="button" value="Start Animation" onclick="startAnimation();">
<input type="button" value="Stop Animation" onclick="stopAnimation();">
</body>
</html>
test.js
var timerFunction = null;
function startAnimation() {
if(timerFunction == null) {
timerFunction = setInterval(animate, 20);
}
}
function stopAnimation() {
if(timerFunction != null){
clearInterval(timerFunction);
timerFunction = null;
}
}
function animate() {
var circle = document.getElementById("circle1");
var x = circle.getAttribute("cx");
var newX = 2 + parseInt(x);
if(newX > 500) {
newX = 20;
}
circle.setAttribute("cx", newX);
}
test.svg
<svg width="500" height="100">
<circle id="circle1" cx="20" cy="20" r="10"
style="stroke: none; fill: #ff0000;"/>
</svg>
I don't understand why I can't insert svg file with object
Thanks for your help
See Dev.To Post: <load-file> Web Component
Use a modern, native W3C standard Web Component <load-svg>
it reads the SVG as text
adds SVG to shadowDOM as DOM element
moves the style element from lightDOM to shadowDOM
So style is only applied to one SVG
<load-svg shadowRoot src="//graphviz.org/Gallery/directed/fsm.svg">
<style>
svg { height:150px } text { stroke: green } path { stroke: red ; stroke-width:3 }
</style>
</load-svg>
<load-svg src="//graphviz.org/Gallery/directed/fsm.svg">
<!-- all HTML here is overwritten -->
</load-svg>
<script>
customElements.define('load-svg', class extends HTMLElement {
async connectedCallback() {
this.style.display = 'none'; // prevent FOUC (provided Custom Element is defined ASAP!)
let src = this.getAttribute("src");
let svg = await (await fetch(src)).text();
if (this.hasAttribute("shadowRoot")) {
this.attachShadow({mode:"open"}).innerHTML = svg;
this.shadowRoot.append(this.querySelector("style") || []);
} else {
this.innerHTML = svg;
}
this.style.display = 'inherit';
}
});
</script>
More complex example: How to make an svg interactive to gather comments/annotations on depicted elements
You can use svgs directly in the HTML. Easiest is to just use the SVG inside the HTML. You can also re-use an svg shape on a page but then the icons have a shadow-dom boundary.
If you use an object or svg tag, it will render just fine but you will lose all information about classes, IDs and so on in the SVG.
Further Information on SVG on css-tricks
More information about how to group and re-use shapes in SVG on css-tricks (and one more, also on css-tricks)
var timerFunction = null;
function startAnimation() {
if (timerFunction == null) {
timerFunction = setInterval(animate, 20);
}
}
function stopAnimation() {
if (timerFunction != null) {
clearInterval(timerFunction);
timerFunction = null;
}
}
function animate() {
var circle = document.getElementById("circle1");
var x = circle.getAttribute("cx");
var newX = 2 + parseInt(x);
if (newX > 500) {
newX = 20;
}
circle.setAttribute("cx", newX);
}
<svg width="500" height="100">
<circle id="circle1" cx="20" cy="20" r="10"
style="stroke: none; fill: #ff0000;"/>
</svg>
<input type="button" value="Start Animation" onclick="startAnimation();">
<input type="button" value="Stop Animation" onclick="stopAnimation();">
<object> tags can be used on many elements, including SVG files, and therefore not recognized as image elements, So:
It's not available on image search. So you can use an <img> tag as fallback (optional but recommended)
You should specify the type of the object
So you can change it like this:
<object type="image/svg+xml" data="test.svg" width="300" height="300">
<img src="test.svg" />
</object>
And another problem is the SVG file. Based on MDN documents :
The xmlns attribute is only required on the outermost SVG element of SVG documents. It is unnecessary for inner SVG elements or inside HTML documents.
so you need to add xmlns parameters to the SVG tag on SVG file like this :
<svg width="500" height="100" xmlns="http://www.w3.org/2000/svg">
<circle id="circle1" cx="20" cy="20" r="10"
style="stroke: none; fill: #ff0000;"/>
</svg>
I made a small simple example that works, checkout this sandBox link
I am trying to make my drawing application work well in Firefox.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.list {
background-color: blanchedalmond;
}
.list-item {
width: 50px;
height: 25px;
background-color: coral;
}
foreignObject {
overflow: visible;
}
</style>
</head>
<body>
<svg width="300" height="200" fill="blue">
<foreignObject width="300" height="25">
<div class="list">
<div class="list-item">a</div>
<div class="list-item">b</div>
<div class="list-item">c</div>
</div>
</foreignObject>
</svg>
<svg class="svg2" width="300" height="200" fill="blue">
<foreignObject width="300" height="25">
<div class="list">
</div>
</foreignObject>
</svg>
<script>
let svg = document.querySelector('.svg2');
svg.addEventListener('mousemove', handleMouseMove)
function handleMouseMove(e) {
console.log(e.offsetX, e.offsetY);
}
setTimeout(() => {
let el = document.querySelector('.svg2 .list');
let a = document.createElement('div')
let b = document.createElement('div');
let c = document.createElement('div');
a.innerHTML = 'a';
b.innerHTML = 'b';
c.innerHTML = 'c';
a.classList.add('list-item')
b.classList.add('list-item')
c.classList.add('list-item')
el.appendChild(a);
el.appendChild(b);
el.appendChild(c);
}, 1000);
</script>
</body>
</html>
In Chrome, both svg show all 3 items.
In Firefox(developer version 78.0b4 (64-bit)), in the first svg, all 3 items are visible, in the second svg, only the first item is visible. Why does the second svg not show all 3 items?
Setting style="overflow: visible" on <svg> solved the same issue for me.
SVG and sub-elements also support overflow="visible" as an attribute (so you can try <foreignObject overflow="visible ... >).
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src='draw.js'></script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="200"></svg>
</body>
</html>
draw.js
function draw() {
var svg = document.getElementsByTagName('svg')[0];
var svgNS = svg.namespaceURI;
var rect = document.createElementNS(svgNS,'rect');
rect.setAttribute('x',5);
rect.setAttribute('y',5);
rect.setAttribute('width',100);
rect.setAttribute('height',36);
rect.setAttribute('fill','#95B3D7');
var link = document.createElement('a');
link.setAttribute('xlink:href', 'http://www.google.com');
link.appendChild(rect);
svg.appendChild(link);
}
$( document ).ready( draw );
The generated HTML looks correct, but the rectangle does not appear:
<a xlink:href="http://www.google.com">
<rect x="5" y="5" width="100" height="36" fill="#95B3D7"></rect>
</a>
In fact, the generated HTML does work, when pasted into an HTML file. So, is there some limitation of the browser using SVG, Javascript and links?
Using Chrome 39.
You need to create an SVG link element and not a html link element i.e. in the SVG namespace
var link = document.createElementNS(svgNS, 'a');
link.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://www.google.com');
You get it right for the rect itself!
INDEX.HTML
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
width: 960px;
padding-top: 40px;
margin: auto;
position: relative;
}
svg {
width: 100%;
max-height: 400px;
}
</style>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type='text/javascript'>
window.addEventListener('load', function () {
d3.xml('iPhone.svg', 'image/svg+xml', function (error, data) {
d3.select('body').node().appendChild(data.documentElement);
var svg = d3.select('svg');
var appScreen = svg.select('#ScreenBackground');
var screenWidth = +appScreen.attr('width'),
screenHeight = +appScreen.attr('height');
var appButton = svg.select('#AppButton')
.on('mouseenter', function () {
appButton.style('fill', '#AB69C6');
})
.on('mouseleave', function () {
appButton.style('fill', '#9B59B6')
})
.on('click', function () {
var x = Math.random() * screenWidth;
var y = Math.random() * screenHeight;
appButton
.transition()
.duration(1000)
.ease('bounce')
.attr('cx', x)
.attr('cy', y);
});
});
});
</script>
iPhone.svg
<?xml version='1.0' encoding='utf-8'?>
<svg width='400px' height='800px' viewBox='0 0 400 800'
version='1.1' xmlns='http://www.w3.org/2000/svg'>
<title> SafeSignal </title>
<description>Created with Sketch (http:/ / www.bohemiancoding.com / sketch) </description>
<defs>
<!-- Define a clipping path the size of the screen -->
</defs>
<!-- iPhone frame -->
<rect id='iPhone' fill='#000000'
x='0' y='0' width='400' height='800' rx='50' ry='50'></rect>
<!-- iPhone home button -->
<circle id='HomeButton' fill='#202020'
cx='200' cy='730' r='40'></circle>
<!-- Apply the clipping path to the screen group -->
<g id='ScreenGroup' transform='translate(20, 80)'
clip-path='url(#ScreenMask)'>
<!-- Screen background -->
<rect id = "ScreenBackground" x ="214" y ="0" width ="102" height ="568" style = "pointer-events: all;" ></rect>
<!-- An interactive button in the app -->
<circle id='AppButton' fill='#9B59B6' cx='180' cy='290' r='50' style='cursor:pointer;'></circle>
</g>
</svg>
taking help from the google , i have made this SVG . now I am trying to make have background as image but i have tried all the ways but everytime i done this ya add any image I have get this error Uncaught TypeError: Cannot read property 'documentElement' of null I dont know where i am going wrong because i am new to this svg
<object type="image/svg+xml"
width="100" height="100" style="float:right"
data="http://blog.codedread.com/clipart/apple.svgz">
<span/></object>
<object id="E" type="image/svg+xml" data="http://srufaculty.sru.edu/david.dailey/svg/ovals.svg" width="320" height="240">
alt : Your browser has no SVG support. Please install Adobe SVG Viewer
plugin (for Internet Explorer) or use Firefox, Opera or Safari instead.
</object>
<!DOCTYPE html>
<html>
<head>
<title>HTML5 SVG demo</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<h1>HTML5 SVG Demo (embed with iframe)</h1>
<p> A nice green circle that was embeded using the HTML "iframe" tag:
<iframe src="green-circle.svg"
width="64" height="64" style="border:1;"></iframe>
</p>
<p>
Tips:
<iframe src="green-circle.svg" style="float:left;margin-right:1cm;"
width="64" height="40" style="border:1;"></iframe>
</p>
</body>
</html>
I have a 'reference' svg with a couple of different groups defined in it for different icons.
Later I define an svg area and use one of the groups. That's working great.
I would like to be able to swap put the group that's referenced in the xlink:href when something is clicked.
The jsFiddle
<!-- SVG SOURCE -->
<svg height="0" width="0" style="position:absolute;margin-left: -100%;">
<g id="unchecked-icon">
<path d="M22.215,44.176c-12.11,0-21.963-9.851-21.963-21.962c0-12.11,9.852-21.962,21.963-21.962 c12.11,0,21.961,9.852,21.961,21.962C44.176,34.325,34.325,44.176,22.215,44.176z M22.215,2.557 c-10.839,0-19.658,8.818-19.658,19.657s8.818,19.658,19.658,19.658c10.839,0,19.657-8.818,19.657-19.658S33.054,2.557,22.215,2.557 z" />
</g>
<g id="checked-icon">
<path d="M22.215,44.176c-12.11,0-21.963-9.851-21.963-21.962c0-12.11,9.852-21.962,21.963-21.962 c12.11,0,21.961,9.852,21.961,21.962C44.176,34.325,34.325,44.176,22.215,44.176z M22.215,2.557 c-10.839,0-19.658,8.818-19.658,19.657s8.818,19.658,19.658,19.658c10.839,0,19.657-8.818,19.657-19.658S33.054,2.557,22.215,2.557 z" />
<polygon points="20.337,32.279 12.274,24.947 14.642,22.344 19.745,26.985 30.005,12.311 32.888,14.327 " />
</g>
</svg>
<!-- SVG SOURCE ends-->
<p>Intial state</p>
<svg class="icon svg" viewBox="0 0 44.429 44.429">
<use xlink:href="#unchecked-icon"></use>
</svg>
<p>After Click</p>
<svg class="icon svg checked" viewBox="0 0 44.429 44.429">
<use xlink:href="#checked-icon"></use>
</svg>
Ok, I found out how you can do this. You need to be changing the Attributes of your <use> DOM Element. In basic JavaScript you would do this with setAttribute() and in jQuery you use attr().
Give the <svg> that will use the graphic and the <use> tag that says which graphic to use ids so that you can grab them with code. After that, it's all about setting up the listeners.
You ask for jQuery, however this is completely doable without so I am providing both ways
JsFiddle
Vector Graphics Toggler
JavaScript
js/index.js
// Toggle to demonstrate both ways of doing this
var BasicJavaScript = true;
// See what way we want to do this
if (BasicJavaScript) {
// When our document loads
window.onload = function() {
var
// Get the svg element we want to be able to change
svgElement = document.getElementById("checkSVG"),
// Get the use element that the svg uses
useElement = document.getElementById("checkUse"),
// Set a toggle bool to know if it should show a check
isChecked = true;
// Make sure the elements exist before we attach listeners
if (svgElement && useElement) {
// Whenever it gets clicked, change it's <use>
svgElement.addEventListener("click", function() {
// If it is checked, make it a check
if (isChecked)
useElement.setAttribute("xlink:href", "#checked-icon");
// Otherwise, no check
else
useElement.setAttribute("xlink:href", "#unchecked-icon");
// Toggle the state
isChecked = !isChecked;
});
}
};
}
else {
// Wait for the document to load
$(document).ready(function() {
// Set a bool for toggling the state
var isChecked = true;
// Add a listener for clicking on the SVG
$("#checkSVG").click(function() {
// If it is checked, make it a check
if (isChecked)
$("#checkUse").attr("xlink:href", "#checked-icon");
// Otherwise, no check
else
$("#checkUse").attr("xlink:href", "#unchecked-icon");
// Toggle state
isChecked = !isChecked;
});
});
}
CSS
css/index.css
#header{
font-family: Arial;
font-size: 2em;
}
#myGraphic{
width: 0;
height: 0;
}
#checkSVG{
width: 200px;
}
HTML
index.html
<!DOCTYPE html>
<html>
<head>
<title>Vector Graphic Changer</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/index.css">
<script src="js/libs/jquery/jquery.js"></script>
<script src="js/index.js"></script>
</head>
<body>
<!--The Definition of the Graphics-->
<svg id="myGraphic">
<g id="unchecked-icon">
<path d="M22.215,44.176c-12.11,0-21.963-9.851-21.963-21.962c0-12.11,9.852-21.962,21.963-21.962 c12.11,0,21.961,9.852,21.961,21.962C44.176,34.325,34.325,44.176,22.215,44.176z M22.215,2.557 c-10.839,0-19.658,8.818-19.658,19.657s8.818,19.658,19.658,19.658c10.839,0,19.657-8.818,19.657-19.658S33.054,2.557,22.215,2.557 z" />
</g>
<g id="checked-icon">
<path d="M22.215,44.176c-12.11,0-21.963-9.851-21.963-21.962c0-12.11,9.852-21.962,21.963-21.962 c12.11,0,21.961,9.852,21.961,21.962C44.176,34.325,34.325,44.176,22.215,44.176z M22.215,2.557 c-10.839,0-19.658,8.818-19.658,19.657s8.818,19.658,19.658,19.658c10.839,0,19.657-8.818,19.657-19.658S33.054,2.557,22.215,2.557 z" />
<polygon points="20.337,32.279 12.274,24.947 14.642,22.344 19.745,26.985 30.005,12.311 32.888,14.327" />
</g>
</svg>
<!--Header-->
<div id="header">My Graphic</div>
<!--The Graphic being used-->
<svg id="checkSVG" viewBox="0 0 44.429 44.429">
<use id="checkUse" xlink:href="#unchecked-icon"></use>
</svg>
</body>
</html>