Javascripts don't work with SVG - javascript

The code below should generate 100 random rectangles. But its not working. Can anyone tell me what I am doing wrong??
<html>
<head>
<script type="text/javascript">
function rectan()
{
var svgns = "http://www.w3.org/2000/svg";
for (var i = 0; i < 100; i++) {
var x = Math.random() * 5000,
y = Math.random() * 3000;
var rect = document.createElementNS(svgns, 'rect');
rect.setAttributeNS(null, 'x', x);
rect.setAttributeNS(null, 'y', y);
rect.setAttributeNS(null, 'height', '50');
rect.setAttributeNS(null, 'width', '50');
rect.setAttributeNS(null, 'fill', '#'+Math.round(0xffffff * Math.random()).toString(16));
document.getElementById('svgOne').appendChild(rect);
}
}
</script>
</head>
<body onload="rectan"();">
<svg id="svgOne" xmlns="http://www.w3.org/2000/svg" width="5000" height="3000">
<rect x="50" y="50"
width="50" height="50"
fill="black"
/>
</svg>
</body>
</html>
All it does is one black rectangle form SVG section. I know that I made a mistake somewhere, but I don't know where.

There seems to be an extraneous double qouote in the onload attribute. You want this...
<body onload="rectan();">

Related

Elements visible only from Inspector, SVG

I've tried to create more circles with button, but it doesnt work. Theyre shown in the Mozilla Inspector after click:
inspector
but theyre not visible for me. I've seen similiar problems here, but there wasn't single one that works. Can you help me please? Atm I have no idea what to do.
circle.js
class Circle {
constructor(id, posx, posy, r, fill) {
this.id = id;
this.posx = posx;
this.posy = posy;
this.r = r;
this.fill = fill;
}}
creator.js
function createCircle() {
let color = ["blue", "black", "red", "green", "purple", "orange", "yellow"]
const circle = new Circle("node", 100, 100, 50, color[0]);
var node = document.createElement("CIRCLE");
node.setAttribute("id", "node");
node.setAttribute("cx", circle.posx);
node.setAttribute("cy", circle.posy);
node.setAttribute("r", circle.r);
node.setAttribute("fill", circle.fill);
document.getElementById("frame").appendChild(node);
console.log(circle.fill);}
body and from index.html
<body onload="myFunction()">
<svg id="sss" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg id="frame" width="1020px" height="820px" viewBox="0 0 1020 820">
<circle id="circle0" cx="100" cy="100" r="50" fill="black" />
</svg>
</svg>
<button onclick="createCircle()">Create circle</button></body>
SVG elements are from a different namespace than typical HTML elements. An HTML document can mix tags from different XML dialects, for example XHTML, which are the standard HTML elements, but also different dialects as well, like the SVG namespace. In order to create the right element from the correct namespace you need to use a different JavaScript method that lets you specify the namespace:
document.createElementNS(namespace, element);
The first argument is the namespace so you should use: "http://www.w3.org/2000/svg", and the second is the element, in this case "circle". So try:
var node = document.createElementNS("http://www.w3.org/2000/svg", "circle");
If you're more interested, check out MDN docs:
https://developer.mozilla.org/en-US/docs/Web/SVG/Namespaces_Crash_Course
https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
#gdanielyan's answer is a good answer. Here is a demo:
class Circle {
constructor(id, posx, posy, r, fill) {
this.id = id;
this.posx = posx;
this.posy = posy;
this.r = r;
this.fill = fill;
}}
function createCircle() {
let color = ["blue", "red", "green", "purple", "orange", "yellow"]
const circle = new Circle("node", 100, 100, 50, color[0]);
var node = document.createElementNS("http://www.w3.org/2000/svg","circle");
node.setAttributeNS(null,"id", "node");
node.setAttributeNS(null,"cx", circle.posx + Math.random()*100);
node.setAttributeNS(null,"cy", circle.posy + Math.random()*100);
node.setAttributeNS(null,"r", circle.r);
let _color=color[~~(Math.random()*(color.length))];
//console.log(_color)
node.setAttributeNS(null,"fill", _color);
document.getElementById("frame").appendChild(node);
}
<svg id="sss" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg id="frame" width="1020px" height="820px" viewBox="0 0 1020 820">
<circle id="circle0" cx="100" cy="100" r="50" fill="black" />
</svg>
</svg>
<button onclick="createCircle()">Create circle</button>

how to animate two svgs in array at same time?

I have a svg array:
var rects = []; //for svg objectsvar
var j=0;
var NS ="http://www.w3.org/2000/svg";
var x = 140, y = 100;
$(document).ready(function() {
function drawRect() {
for(var i=0; i<4; i++) {
var rect = document.createElementNS(NS, 'rect');
rect.setAttributeNS(null, 'id', "srect"+i);
rect.setAttributeNS(null, 'x', x);
rect.setAttributeNS(null, 'y', y);
rect.setAttributeNS(null, 'height', '80');
rect.setAttributeNS(null, 'width', '80');
rect.setAttributeNS(null, 'fill', '#000000');
rects.push(rect);
document.getElementById('svgOne').appendChild(rects[i]);
x+=80;
}
moveTwoRect(j);
}
}
function moveTwoRect() {
for(var j=0; j<4; j++) {
$(function () {
$('#'+rects[j].id).animate({y: '50px'}, 3000);
$('#'+rects[j+1].id).animate({y: '50px'}, 3000);
});
}
}
$("#bu").click(drawRect);
});
</script>
<svg xmlns:svg="http://www.w3.org/2000/svg" id="svgOne"
xmlns="http://www.w3.org/2000/svg" width="800" height="600">
This browser is not support svg. Please Upgrade Your browser version
or Use Other browser.
<rect width="800" height="400" style="fill:white; stroke-width:3;stroke:black">
</svg>
<button id='bu1'>Push Me</button>
I want to move two rects at same time.
for example, rects[0], rects[1] move at same time.
and rects[1], rects[2] move at same time.
other rects move like this.
but all of rects move at same time when i push button.
What do i do for this problem?
I want use only javascript or jquery.

Draw a check mark inside the rect tag in svg using js

I have created a small rect using js and svg, here is the code for it:
Html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<svg id="svgOne" xmlns="http://www.w3.org/2000/svg" width="5000" height="3000">
</svg>
</body>
</html>
and js:
var svgns = "http://www.w3.org/2000/svg";
var x = 50,
y = 30;
var rect = document.createElementNS(svgns, 'rect');
rect.setAttributeNS(null, 'x', x);
rect.setAttributeNS(null, 'y', y);
rect.setAttributeNS(null, 'height', '50');
rect.setAttributeNS(null, 'width', '50');
rect.setAttributeNS(null, 'fill', 'grey');
document.getElementById('svgOne').appendChild(rect);
and here is the jsfiddle.
I want to add a check mark inside the rectangle, the check mark looks like:
How am I supposed to do this?
You can use the svg path element to crate your check mark. The tricky part about the path element is the d attribute, which will describe the path combining several instructions. Here is some good information on how the d attribute works.
Take a look at the example and i'm sure you will get the idea.
var svgns = "http://www.w3.org/2000/svg";
var x = 50,
y = 30;
// create group element
var group = document.createElementNS(svgns, 'g');
var rect = document.createElementNS(svgns, 'rect');
// create the path element
var checkMark = document.createElementNS(svgns, 'path');
// set group position
group.setAttributeNS(null, 'transform', 'translate('+ x + ', '+ y + ')');
rect.setAttributeNS(null, 'height', '50');
rect.setAttributeNS(null, 'width', '50');
rect.setAttributeNS(null, 'fill', 'grey');
// set path attributes
checkMark.setAttributeNS(null, 'd', 'M7.375,33.25 c0,0,10,11.375,14.125,11.375S44.875,8,44.875,8');
checkMark.setAttributeNS(null, 'fill', 'none');
checkMark.setAttributeNS(null, 'stroke-linecap', 'round');
checkMark.setAttributeNS(null, 'style', 'stroke:rgb(255,255,255);stroke-width:6');
// append elements to group
group.appendChild(rect);
group.appendChild(checkMark);
// append group to svg
document.getElementById('svgOne').appendChild(group);
// clone your checkmark
var checkMarkCopy = group.cloneNode(true);
checkMarkCopy.setAttributeNS(null, 'transform', 'translate(100, 100)');
document.getElementById('svgOne').appendChild(checkMarkCopy);
<svg id="svgOne" xmlns="http://www.w3.org/2000/svg" width="5000" height="3000"></svg>
When I executed the web page I got the error:
Uncaught TypeError: Cannot read property 'appendChild' of null
at: document.getElementById('svgOne').appendChild(group);
So I rearranged stuff according to what I learned from:
Saved from: https://www.sitepoint.com/community/t/creating-a-svg-element/5929/
ADDED: <title> in the <head> (not important at all).
MOVED: </head> to just after the <title>.
MOVED: <body> and <h2> to just after </head>.
ADDED: <div id="container"/> to <body>. //Will contain all of the SVG content.
NOTE: At this point, the container has been added to the <body> and the <script> is now positioned INSIDE the <body>.
DELETED the original SVG element from the : => <svg id="svgOne" xmlns="http://www.w3.org/2000/svg" width="500" height="300"> </svg>.
ADDED the creation of a new SVG element in the <script>:
var svg = document.createElementNS(svgns, "svg"); //Create an svg tag in SVG's namespace
svg.setAttribute("width", "300");
svg.setAttribute("height", "400");
DELETED the original appendChild(group): => document.getElementById('svgOne').appendChild(group);
REPLACED it with the new appendChild(group):=>
svg.appendChild(group);
DELETED the original appendChild(checkMarkCopy): => document.getElementById('svgOne').appendChild(checkMarkCopy);
REPLACED it with the new appendChild(checkMarkCopy):=>
svg.appendChild(checkMarkCopy);
ADDED: => document.getElementById("container").appendChild(svg);
This worked in Chrome Version 58.0.3029.110.
In the Chrome console, the framework looks like:
Framework of web page.

Dragging SVG element over another SVG element

Is there any way i can drag an SVG element over another SVG element? I tried but like in this tutorial i can only drag the one i placed the second over the first one. There is no way i can drag first one over the second without problems.
Does anyone know how to solve this?
Here is the whole tutorial: http://www.petercollingridge.co.uk/book/export/html/437
I was writing it before I saw that #Strat-O gave you the same approach.
So here is a commented example of that :
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="200">
<style>
.draggable {
cursor: move;
}
</style>
<script type="text/ecmascript"><![CDATA[
var selectedElement = 0;
var currentX = 0;
var currentY = 0;
var currentMatrix = 0;
function cloneToTop(oldEl){
// already at top, don't go farther…
if(oldEl.atTop==true) return oldEl;
// make a copy of this node
var el = oldEl.cloneNode(true);
// select all draggable elements, none of them are at top anymore
var dragEls= oldEl.ownerDocument.documentElement.querySelectorAll('.draggable');
for(i=0; i<dragEls.length; i++){
dragEls[i].atTop=null;
}
var parent = oldEl.parentNode;
// remove the original node
parent.removeChild(oldEl);
// insert our new node at top (last element drawn is first visible in svg)
parent.appendChild(el);
// Tell the world that our new element is at Top
el.atTop= true;
return el;
}
function selectElement(evt) {
selectedElement = cloneToTop(evt.target);
currentX = evt.clientX;
currentY = evt.clientY;
currentMatrix = selectedElement.getAttributeNS(null, "transform").slice(7,-1).split(' ');
for(var i=0; i<currentMatrix.length; i++) {
currentMatrix[i] = parseFloat(currentMatrix[i]);
}
selectedElement.setAttributeNS(null, "onmousemove", "moveElement(evt)");
selectedElement.setAttributeNS(null, "onmouseout", "deselectElement(evt)");
selectedElement.setAttributeNS(null, "onmouseup", "deselectElement(evt)");
}
function moveElement(evt) {
var dx = evt.clientX - currentX;
var dy = evt.clientY - currentY;
currentMatrix[4] += dx;
currentMatrix[5] += dy;
selectedElement.setAttributeNS(null, "transform", "matrix(" + currentMatrix.join(' ') + ")");
currentX = evt.clientX;
currentY = evt.clientY;
}
function deselectElement(evt) {
if(selectedElement != 0){
selectedElement.removeAttributeNS(null, "onmousemove");
selectedElement.removeAttributeNS(null, "onmouseout");
selectedElement.removeAttributeNS(null, "onmouseup");
selectedElement = 0;
}
}
]]> </script>
<g>
<circle/>
</g>
<rect x="0.5" y="0.5" width="399" height="199" fill="none" stroke="black"/>
<rect class="draggable" id="blue" x="30" y="30" width="80" height="80" fill="blue" transform="matrix(1 0 0 1 46 18)" onmousedown="selectElement(evt)"/>
<rect class="draggable" id="green" x="160" y="50" width="50" height="50" fill="green" transform="matrix(1 0 0 1 51 11)" onmousedown="selectElement(evt)"/>
</svg>
Unfortunately, there is only one way to make an element appear in front of another element in SVG and that is to remove the lower element then turn around and redraw it. There is no z-index or other helpful attribute that you can set. I spent a bit of time on this and that is my conclusion.
There is one upside and that is by removing and redrawing it, it ensures that the display order of all of the elements is maintained whereas if you have to maintain z-indexes, managing the numbers can cause its own set of issues.

creating circles with svg and javascript

(UPDATED) I'm having some issues regarding svg and javascript. What I want to create is a series of circles on top of one another, with their radius (r) values increasing by one each time the loop goes round, so that it creates some sort of a pattern. Here is what I have so far(for loop values are from another forum post, I would rather do it with a while loop that would execute 10 times) -
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Dynamic SVG!</title>
</head>
<defs>
<svg height="10000" width="10000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle id="cir1" cx="300" cy="300" r="40" stroke="yellow" stroke-width="" fill="none"/>
</svg>
</defs>
<script>
var svgns = "http://www.w3.org/2000/svg";
for (var x = 0; x < 5000; x += 50) {
for (var y = 0; y < 3000; y += 50) {
var circle = document.createElementNS(svgns, 'circle');
circle.setAttributeNS(null, 'x', x);
circle.setAttributeNS(null, 'y', y);
circle.setAttributeNS(null, 'height', '50');
circle.setAttributeNS(null, 'width', '50');
document.getElementById('cir1').appendChild(circle);
}
}
</script>
<body>
</body>
</html>
Any help out there?
Thanks.
Ok, so this is, what I had to fix in order to get your code working:
You append to the circle element, but should append to the svg-container. A circle element has no child elements.
You did not set any styles for the circles, so they were transparent.
The coordinates in a circle element are called cx and cy instead of x and y.
The <defs> element should be a child of the <svg> element. Also everything within it wont be rendered.
JavaScript
var svgns = "http://www.w3.org/2000/svg",
container = document.getElementById( 'cont' );
for (var x = 0; x < 500; x += 50) {
for (var y = 0; y < 300; y += 50) {
var circle = document.createElementNS(svgns, 'circle');
circle.setAttributeNS(null, 'cx', x);
circle.setAttributeNS(null, 'cy', y);
circle.setAttributeNS(null, 'r', 50);
circle.setAttributeNS(null, 'style', 'fill: none; stroke: blue; stroke-width: 1px;' );
container.appendChild(circle);
}
}
HTML
<svg id="cont" height="1000" width="1000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle id="cir1" cx="300" cy="300" r="40" stroke="yellow" stroke-width="" fill="none" />
</svg>
Example Fiddle
I also adjusted your sizes as for a mere test, they were quite big.

Categories

Resources