Having problems scripting SVGs - javascript

I'm having some trouble with manipulating SVGs through javascript. I'd like to increase the length of a line through clicking a button. I've included this code in the head tag:
<script type="text/javascript">
x=135;
y=135;
var container = document.getElementById("svgbox");
var mySvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
function svg() {
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute("height","300px");
mySvg.setAttribute("width","300px");
container.appendChild(mySvg);
}
function line() {
x=x-10;
y=y-10;
var L1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
L1.setAttribute("x1", "100"); L1.setAttribute("y1", "100");
L1.setAttribute("x2", x); L1.setAttribute("y2", y);
L1.setAttribute("stroke", "#05adc7");
L1.setAttribute("stroke-width", "2px");
mySvg.appendChild(L1);
}
</script>
This is the body text:
<body onload="svg()">
<form>
<input type="button" onClick="line()" />
</form>
<div id="svgbox">
</div>
</body>
But when I click on the button, I get an error telling me that the variable "container" is null. Does anyone know what the problem is?

It works if you put the line var container = document.getElementById("svgbox"); in the svg function.
function svg() {
var container = document.getElementById("svgbox");
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute("height","300px");
mySvg.setAttribute("width","300px");
container.appendChild(mySvg);
}
The reason container is null in your code is because the DOM has not loaded yet when the line var container = document.getElementById("svgbox"); gets executed.
You need to declare container after either the DOMContentLoaded event or window.onload event is fired.

This is a common gotcha in DOM scripting, for both SVG and HTML. The problem is that the svgbox element is not yet loaded when the JavaScript executes. The easiest solution is to simply move your script tag so that it is the last element in the document. This is a bit ugly, though, so most JavaScript libraries include a method that accepts a callback to execute after the document has been loaded. For example, if you were using jQuery, then your script tag would look like the following:
<script type="text/javascript">
$(document).ready(function(){
x=135;
y=135;
var container = document.getElementById("svgbox");
var mySvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg = function() {
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute("height","300px");
mySvg.setAttribute("width","300px");
container.appendChild(mySvg);
}
line = function() {
x=x-10;
y=y-10;
var L1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
L1.setAttribute("x1", "100"); L1.setAttribute("y1", "100");
L1.setAttribute("x2", x); L1.setAttribute("y2", y);
L1.setAttribute("stroke", "#05adc7");
L1.setAttribute("stroke-width", "2px");
mySvg.appendChild(L1);
}
})
</script>

Related

DOM Manipulation Click Mouse Event

I was trying to change the color of the background of the web page with a mouse click, below are the lines for the same:
let bodyvar = document.querySelector('body');
bodyvar.addEventListener("click",generate);
function generate(){
bodyvar.style.backgroundColor = "red";
}
When I test individual lines in console it is selecting the body and the function and everything works correctly individually but not on the actual page.
I have just started leaning JS so am not sure what am missing here, will I also need to consider the co-ordinates that the mouse clicks on?
I suspect that the <body></body> is empty. Add some content, or define the width and height.
let bodyvar = document.querySelector('body');
bodyvar.style.minWidth = "100vw";
bodyvar.style.minHeight = "100vh";
bodyvar.addEventListener("click",generate);
function generate(){
bodyvar.style.backgroundColor = "red";
}
Alternatively, I can use <HTML> instead of <body>.
let bodyvar = document.querySelector('html');
bodyvar.addEventListener("click",generate);
function generate(){
bodyvar.style.backgroundColor = "red";
}

s.substr is not a function

I am using canvg, but when I run this:
jQuery("#print").on("click", function() {
mySvg();
});
function mySvg() {
var svg = jQuery("#map svg");
canvg(document.getElementById('canvas'), svg);
}
I get this in console
canvg.js:58 Uncaught TypeError: s.substr is not a function
Here it is a jsFiddle
Siguza is correct, you want to get the inner HTML of your SVG so (assuming #map is the direct parent of your target svg):
var svg = jQuery('#map');
var txt = svg.innerHTML;
Then you want to pass the txt variable as your second canvg() argument.

Function undefined for onclick event -HTML5 canvas

I'm just starting out working with the HTML5 canvas and I want to use onclick to call as js function in my document.
However, despite declaring the function in my JS, I still get [function name] is not defined when clicking.
The function is defined as such:
function draw_b() {
var b_canvas = document.getElementById("b"); // finds the canvas in the DOM
var b_context = b_canvas.getContext("2d"); // context for drawing. No 3D option yet
b_context.fillRect(50, 25, 150, 100);
}
The click event is included as such:
onclick="draw_b();return false"
Yet when I click the element, I get:
draw_b is not defined
JSFiddle
In JSfiddle you need to use the No Wrap - In <head> option so the function is defined when used inline for the HTML elements. Also var b_canvas = document.getElementById("b"); should be var b_canvas = document.getElementById("a");
jsFiddle
You are using the wrong ID
var b_canvas = document.getElementById("a");// Use `a` not `b`
Jsfiddle doesn't like onclick="" so you need to use addEventListener from JavaScript.
var a_canvas = document.getElementById("a");
a_canvas.addEventListener("click",draw_b);
function draw_b() {
var b_canvas = document.getElementById("b"); // finds the canvas in the DOM
var b_context = b_canvas.getContext("2d"); // context for drawing. No 3D option yet
b_context.fillRect(50, 25, 150, 100);
}
canvas {
border: 1px dotted;
}
<canvas id="a" width="300" height="225"></canvas>
<canvas id="b" width="300" height="225"></canvas>

How to programmatically ng-bind a property on an svg element?

I'd like to bind a background color to an svg element. I have an external svg file that I'm referencing, myfile.svg, inside of this file there's a circle with the id 'mycircle'.
So my html looks like:
<div ng-controller="MyCtrl">
<embed src="myfile.svg" id="mySvg"/>
</div>
I have a controller that looks like:
function MyCtrl($scope) {
$scope.myfill = 'yellow';
}
Now I'd like to set up the binding programmatically, this is what I do:
var mySvg = document.getElementById("mySvg");
mySvg.addEventListener("load", function() {
var svg = mySvg.getSVGDocument();
var mycircle = svg.getElementById("mycircle");
//this works:
//mycircle.setAttribute("fill", "yellow");
$(mycircle).attr('ng-bind','myfill');
});
However, this doesn't set the fill. I'm thinking I might need to use angular "compile" or something in order to get this to work (?) can anyone clue me in on how to do this?
Yes you need to compile. Should bind as an exp and compile against the scope. Below snippet should work.
var mySvg = document.getElementById("mySvg");
mySvg.addEventListener("load", function() {
var svg = mySvg.getSVGDocument();
var mycircle = angular.element(svg.getElementById("mycircle"));
mycircle.attr('fill', '{{myfill}}');
$compile(mycircle)($scope);
});

Appending to body with javascript

I have an assignment to make several bugs fly around the screen randomly, but I'm having problems getting divs to be added to the html body through javascript.
<head>
<title>Fly little bug! Fly!</title>
<script type="text/javascript">
/* <![CDATA[ */
var numBugs = 0;
var body = document.getElementsByTagName("body");
function bug(startX, startY, xSpeed, ySpeed){
var self = this;
this.xPos = startX;
this.yPos = startY;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.divId = "bug" + numBugs;
this.div = document.createElement("div");
this.div.innerHTML = "test";
body.appendChild(self.div);
this.fly = function(){
self.xPos += self.xSpeed;
self.yPos += self.ySpeed;
}
this.fly();
this.flyInterval = setInterval(function(){ self.fly(); },5000);
numBugs++;
}
/* ]]> */
</script>
</head>
<body onload = "var bug1 = new bug(10, 20, 5, 3);">
</body>
</html>
I can see two problems.
The getElementsByTagName function returns an array of elements. You have to be explicit that you want the first element of the array.
var body = document.getElementsByTagName("body")[0];
You're essentially saying "give me all the tags in the document of type 'body'". It gives you a list of tags, and you have to get the first one even though there should only be one "body" in any HTML document. The [0] in the code above gives you the first one.
You are trying to access the body before it's created. The <script> occurs in the document before the <body> tag, so at the time the script is executed, the body doesn't exist. You need to move the call to getElementsByTagName inside the bug() function.
document.body.innerHTML += '<div>Div Content</div>';
Look into jQuery if you want to make simple DOM manipulation easier on yourself.

Categories

Resources