I'm trying to make a very simple modification of a circle SVG. The script code should change the radius of the circle, but nothing seems to happen. (using the same format, I am able to change the color but none of the other elements of the circle).
<!DOCTYPE html>
<html>
<body>
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="50" fill="red" id="cir"/>
</svg>
<script>
document.getElementById("cir").r = 2000;
</script>
</body>
</html>
"r" is no property of the element, it's an attribute. Use this:
document.getElementById("cir").setAttribute("r", 2000);
Related
I am trying to use d3.zoom on an inline svg, specifically a map of the USA (please note that I am very inexperienced at d3js). After some research I found a simple tutorial for using d3.zoom https://www.datamake.io/blog/d3-zoom/.
The issue I have now is that it just doesn't work. There is no error which shows up. It just does nothing.
Here is the HTML code with the svg map.
<div id="map">
<?xml version="1.0" encoding="UTF-8"?>
<svg id="usa_svg" height="800" width="1200" version="1.1" viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg">
<g id="USA">
<rect height="600" width="1200"></rect>
<!-- paths here -->
</g>
</svg>
</div>
Here is the JavaScript
var usa = d3.select("svg")
var rect = d3.select("rect");
var zoom = d3.zoom().on("zoom", zoomed);
rect.call(zoom);
function zoomed() {
var transform = d3.event.transform;
usa.attr("transform", transform.toString());
}
I have no clue what I am doing wrong. Is it a syntax error? Am I just missing a vital part of the code? Help would be much appreciated.
If I am embedding an SVG using an <object> tag, is it possible to use normal DOM methods to access the children elements?
Example
First a simple SVG:
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"
viewBox="0,0 100, 100">
<defs>
<style>
#cls-1 {
fill: none;
stroke: #000;
stroke-width: 4;
}
</style>
</defs>
<title>Circles</title>
<g id="cls-1">
<circle cx="30" cy="30" r="10" />
<circle cx="60" cy="60" r="10" />
</g>
</svg>
Then an HTML file that embeds the SVG using and tries to access the group defined in the SVG within a script:
<html>
<body>
<object
type="image/svg+xml"
height="200px"
data="mysvg.svg"
></object>
<button onclick="myAnimate()" />
<script>
const myAnimate = () => {
const group = document.getElementById("cls-1");
};
</script>
</body>
</html>
Wy doesn't this work?
I see in the devtools that the first child of this is #document. So it seems to have it's own DOM, I think I read this, but still have not wrapped my head around how it works.
Is there a way to access the element with id "cls-1" from JS?
EDIT: one way to make this work is to add the script within the svg itself; the DOM methods work normally for the DOM in the SVG
My index.html is
<object id="embed" data="test.html" width="500" height="500"
type="text/xml"></object>
<script>
var test = document.getElementById("test");
var embed = document.getElementById("embed");
test.style.fill = "purple";
</script>
My test.html is
<style>
#test {
cx: 80%;
fill: green;
}
</style>
<svg width="500" height="500">
<circle id="test" cx="50%" cy="50%" r="40%"
stroke="black" stroke-width="1" fill="red" />
</svg>
I would like to apply css from the parent document to the loaded svg. I would also like to manipulate the svg using javascript in the parent document. The css works. JavaScript also works. They both modify position and fill, but they only work from the test.html document.
How do I manipulate and style embedded SVGs? I have a folder full of them and they can be mixed and relabeled, which is necessary for my larger project. I got a David Lynch plot sized headache reading up on the trainwreck of html imports and am avoiding them for now.
Prefer no jQuery.
It seems like a contrived problem but I am trying to make a proof of concept of an HTML 5 document, containing inline SVG, which itself contains a <foreignObject> element with an HTML canvas inside. I then want to call a JavaScript function to draw on the canvas.
(How I got here: I want to use SVG as a format for defining an animated graphical view which can contain graphs, which are animated by replacing a dummy element in the SVG with a live graph using JavaScript / ECMAScript, and one of the JavaScript libraries we are considering to generate the graphs (Flot) uses an HTML canvas for the view, so I want to inject this canvas into the SVG view. A further complication is we ideally want this system to run on local files, on the file:// protocol, meaning we can't run scripts on external files (e.g. referenced with <object> or <iframe>) because browsers block them, hence the inline SVG.)
Here is an HTML source illustrating the problem:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas Test</title>
<script type="text/javascript">
function draw_box() {
var canvas = document.getElementById("box_canvas");
var context = canvas.getContext("2d");
context.fillRect(50, 20, 50, 60);
}
</script>
</head>
<body>
<h1>Canvas Test
<p>
<svg width="400" viewBox="-10 -10 268 108">
<rect style="fill: #a0a0a0" x="8" y="8" width="240" height="80" rx="40" ry="40"/>
<g>
<rect style="fill: #0000ff" x="0" y="0" width="240" height="80" rx="40" ry="40"/>
<rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke-linejoin: round; stroke: #000000" x="0" y="0" width="240" height="80" rx="40" ry="40"/>
<foreignObject x="120" y="25" width="150" height="100">
<canvas id="box_canvas" width="150" height="100" style="border:1px dotted;float:left">Canvas alt text</canvas>
</foreignObject>
</g>
</svg>
<p>
<button type="button" onclick="draw_box();return false">Animate</button>
</body>
</html>
The above page doesn't display the canvas at all in IE 11. In the latest version of Chrome it displays the canvas, but the effects of the JavaScript function called by the button - drawing the black box - only show up if you click on the SVG image.
What I need to know:
1) Is there something wrong with what I've written - e.g. am I missing some function call to make the SVG or foreignObject update after I have drawn on the canvas?
2) Is this a lost cause? Is the specification of <foreignObject> etc. immature enough that I could never be confident that this will work, even if we can control what browser the user views the document in? It's actually fine if this is the case because we can just say going forward that we need our graph library to generate SVG and not HTML.
Thanks a lot
I am trying to implement the hammer.js with svg files and without using any jquery. I'm trying to use the sample code from the hammer.js site {https://github.com/EightMedia/hammer.js/wiki/Getting-Started}. I have the external javascripts called like this.
<script src="javascript/hammer.js" type="text/javascript"></script>
My javascript is as follows:
<script type="text/javascript">
//<![CDATA[
var element = document.getElementById("testsvg");
var hammertime = Hammer(element).on('doubletap', function(event){
alert("doubletap!");
return false;
}
);
//]]>
</script>
My svg looks like the following.
<svg version="1.1" id="testsvg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="585px" height="230" viewBox="0 0 585 230" enable-background="new 0 0 585 230" xml:space="preserve">
<rect x="10" y="10" height="210" width="565" style="stroke:#006600; fill: #00cc00"/>
</svg>
Starting out, I'm just trying to get any detection to work. I do not get any alert when I double tap. I have also tried to implement this with the hammer.fakemultitouch.js plugin on my desktop. Neither the desktop or touch environment do anything.
Anyone have any idea what I might be doing wrongly?
Thanks,
--christopher
First make sure hammer.js is loading correctly. If it is, then you are most likely executing the javascript before the DOM is loaded. The easiest way to fix this is to place your <script> right before the closing </body> tag (near the bottom of your html file). You can also wrap your code in a load event function such as...
window.onload = function(){
var element = document.getElementById("testsvg");
var hammertime = Hammer(element).on('doubletap', function(event){
alert("doubletap!");
return false;
});
}