Get width or height svg rectangle javascript - javascript

I can get the width of my object svg in javascript and save the value in a variable. this is my object
<rect id="cercle1" x="5" y="25" width="50" height="50" stroke-width="1" stroke="#0E0E0E" style="fill:red; stroke:black; stroke-width:2"; />
I try this:
document.getElementById('cercle1').width.value;
thanks for help

You can use the getAttribute function:
document.getElementById('cercle1').getAttribute("width");
That will get you the String from the HTML code. As Phrogz mentioned it, you might want a number instead, or the actual value (that might be different). If so, refer to his answer.

The width attribute is an SVGAnimatedLength property. As such, you need to:
// If you want the original value
var w = document.getElementById('cercle1').width.baseVal.value;
// If it is animated and you want the current animated value
var w = document.getElementById('cercle1').width.animVal.value;
Or, if just want what's in the source code:
var w = document.getElementById('cercle1').getAttribute('width')*1; // convert to num

You can try this:
var obj = document.getElementById("cercle1"); // reference to the object tag
var rect = obj.getBoundingClientRect(); // get the bounding rectangle
alert(rect.width);
alert(rect.height);
Or this:
var obj = document.getElementById("cercle1"); // reference to the object tag
var svgdoc = obj.contentDocument; // reference to the SVG document
var svgelem = svgdoc.documentElement; // reference to the SVG element
alert(svgelem.getAttribute("width"));
Here is a working JSFiddle example.
From the comments from Phrongz: Note that the bounding rect will account for transforms, which may or may not be desired.

Just in case you had created your rect dynamically, then the below solution is valid
var rect = document.createElementNS(svgns, "rect");
rect.setAttribute('width', '200px');
rect.setAttribute('height', '200px');
var width= rect.width.baseVal.value;
var height= rect.width.baseVal.value;

Related

adding svg rectangle to dom using js

I would add a rectangle as on each Node element
the rect is added only in the last element.
ngAfterViewInit() {
let rect : NodeList = this.synoptic.nativeElement.querySelectorAll("#stops g");
let rect2 = document.createElementNS('','rect');
rect2.setAttribute("fill","none");
rect.forEach((elm : Node) => {
console.log(elm.firstChild) #### Well selecting the first element
elm.insertBefore(rect2,elm.firstChild);
console.log(elm) ####rect added
})
### rect is awailable only in the last elm
}
Edit I'm using angular And my code is running inside ngAfterViewInit() hook
Here a stackblitz demo
Try it this way by adding namespace and attributes required for rect
(function() {
let rect = document.querySelectorAll("#stops g");
rect.forEach(e => {
let rect2 = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect2.setAttribute("fill", "#000");
rect2.setAttribute('x', e.getAttribute('x'));
rect2.setAttribute('y', e.getAttribute('y'));
rect2.setAttribute('height', '50');
rect2.setAttribute('width', '50');
e.appendChild(rect2);
});
})();
<svg id="stops" xmlns="http://www.w3.org/2000/svg">
<g x="0" y="0"></g>
<g x="100" y="100"></g>
</svg>
Angular Working Fiddle
The SVG namespace is 'http://www.w3.org/2000/svg', and not the empty string.
Additionally a rect with fill none won't be visible, it either needs a fill or a stroke and appears to have neither specified.
Finally it needs a non-zero width and height.

Rect doesn't visualized after append

Context
I'm using react js and svg.draw.js for draw svg elements inside a div, the user can draw rect or other shapes and he can see shapes drawed in precedent session.
For make the last functionality I stored the entire svg element drawed as string so when ComponentDidMount() method is fired, it can parse it to image/svg+xml element and then it can append the svg node to the svg root.
So to try this solution in ComponentDidMount() I have create a rect node to append.
Issue
When I try to append the rect element, it doesn't visualized but it's present inside the root element.
This is what I see in console, the rect element is what I have to append.
Code
This is what it's present in ComponentDidMount() method.
componentDidMount(){
/*
*
*irrilevant code*/
const scriptDraw = document.createElement("script");
scriptDraw.src = "svgDrawer.js"; //svg.draw.js
scriptDraw.setAttribute("id","drawer")
scriptDraw.async = true;
document.body.appendChild(scriptDraw);
var str = '<rect id="SvgjsRect1008" class="selected" width="124" height="89" stroke="#3399ff" stroke-width="2" fill-opacity="1" fill="#3399ff" x="236" y="160" name="dawdawad"></rect>'
var parser = new DOMParser();
var doc = parser.parseFromString(str, "image/svg+xml");
scriptDraw.addEventListener("load",function(){
var map = document.getElementById("planimetriaSVG"); //svg root
map.appendChild(doc.documentElement);
})
}
Add a namespace attribute to the rect element so parseFromString knows its supposed to be an SVG element i.e.
var str = '<rect xmlns="http://www.w3.org/2000/svg" id="SvgjsRect1008" class="selected" width="124" height="89" stroke="#3399ff" stroke-width="2" fill-opacity="1" fill="#3399ff" x="236" y="160" name="dawdawad"></rect>'
var parser = new DOMParser();
var doc = parser.parseFromString(str, "image/svg+xml");

Jquery: convert SVG to PNG with new size

I´m using the following function to transform an SVG into a PNG and offer it as a download:
<svg id="chart">
...some contenthere
</svg>
function() {
var svg = $("#chart")[0],
bBox = $('#chart')[0].getBBox();
var width = bBox.width*2,
height = bBox.height*2;
var canvas = $("canvas")[0],
serializer = new XMLSerializer(),
svgString = serializer.serializeToString(svg);
canvas.width = width;
canvas.height = height;
canvg(canvas, svgString);
var dataURL = canvas.toDataURL('image/png'),
data = atob(dataURL.substring('data:image/png;base64,'.length));
asArray = new Uint8Array(data.length);
for (var i = 0; i < data.length; ++i) {
asArray[i] = data.charCodeAt(i);
}
var blob = new Blob([asArray.buffer], {type: 'image/png'});
saveAs(blob, 'climatechart.png');
}
It actually works fine, despite the fact that the output image is the same size as the SVG in the browser. How can i set a new size for the image? I also tried to get the size directly from the svg not the BBox, but it was the same.
This solution is based on a remote formatting server and not local code. It uses XSL FO server-side to render SVG to bitmap directly, allowing you to set the resolution for high quality output.
Documentation: http://www.cloudformatter.com/CSS2Pdf.APIDoc.Usage
Example: http://jsfiddle.net/g75t4oyq/
Code Implementation for JPG format # 300dpi from SVG in div:
click="return xepOnline.Formatter.Format('JSFiddle', {render:'newwin', mimeType:'image/jpg', resolution:'300', srctype:'svg'})";
jQuery('#buttons').append('<button onclick="'+ click +'">JPG #300dpi</button>');
You can easily resize a canvas as you can draw it as a canvas. The following example ignores any of the SVG rendering, which is working fine according to your question, but it does show how you can easily resize a canvas using another canvas:
var myCanvas = document.createElement('canvas');
var myCtx = myCanvas.getContext('2d');
myCanvas.width = 200;
myCanvas.height = 200;
myCtx.arc(100, 100, 100, 0, Math.PI * 2, true);
myCtx.fill();
var seCanvas = document.createElement('canvas');
var seCtx = seCanvas.getContext('2d');
seCanvas.width = 200;
seCanvas.height = 200;
seCtx.drawImage(myCanvas, 0, 0, 100, 100);
document.body.appendChild(myCanvas);
document.body.appendChild(seCanvas);
After that, you can simply continue the process using this new canvas.
SVG documents can be resized via height and width attributes if the svg element defines a viewBox attribute depending on its size; e.g.
<svg width="500" height="200" viewBox="0 0 50 20" >
Once the viewBox has been set, the scaling of svg in canvas works as you coded.
Ok, thanks for the suggestions, i finally found a solution that perfectly fits (according to Cédric Hartlands hint). The viewbox attribute was the part that was completely missing in my code. The viewbox is defined as the following:
viewbox = "x y width height"
So to scale up the <svg> and ALL the elements in it, it is necessary to make sure that width and height of the viewbox exactly match the new width and height of the <svg> element:
//original version
<svg> width="100" height="100" viewbox="0 0 100 100" preserveAspectRatio="xMinYMin meet"</svg>
//scaled up version
<svg> width="200" height="200" viewbox="0 0 200 200" preserveAspectRatio="xMinYMin meet"</svg>
If i convert the scaled up svg into a canvas, it fits the whole image without loosing any quality (which is the biggest benefit of vector graphics anyway). Cannot believe it took my so long to get that.

Element created with createElementNS doesn't show

I'm trying to create a new <img> with the <svg> tag with JavaScript every time I click on the button. When I see the result in the console firebug it works correctly, but nothing on screen displays.
What I want is for an image <svg> to appear after the last one every time you click the button.
Thanks in advance.
var svgNS = "http://www.w3.org/2000/svg";
mybtn.addEventListener("click", createCircleSVG);
function createCircleSVG(){
var d = document.createElement('svg');
d.setAttribute('id','mySVG');
document.getElementById("svgContainer").appendChild(d);
createCircle();
}
function createCircle(){
var myCircle = document.createElementNS(svgNS,"circle"); //to create a circle."
myCircle.setAttributeNS(null,"id","mycircle" + opCounter++);
myCircle.setAttributeNS(null,"cx",25);
myCircle.setAttributeNS(null,"cy",25);
myCircle.setAttributeNS(null,"r",100);
myCircle.setAttributeNS(null,"fill","black");
myCircle.setAttributeNS(null,"stroke","blue");
document.getElementById("mySVG").appendChild(myCircle);
}
Create a SVG:
var svg = document.createElementNS(ns, 'svg');
First function:
function createSVG() { ... }
Second function:
function createSVGCircle() { createSVG() ... }
Or separated:
createSVG();
createSVGCircle();
Example
You need to create the svg element in the SVG namespace using createElementNS (like you already do for the circle) e.g.
var d = document.createElementNS(svgNS, 'svg');
giving the SVG element a width and height is also necessary
d.setAttribute("width", "100%");
d.setAttribute("height", "100%");
Note here we can use setAttribute as the attributes are in the null namespace. You can convert the circle setAttributeNS calls too if you want.

Create a group that doesnt depend on a Snap instance

Here is what I want to do :
var a = Snap("#id");
var group = new SnapGroup(); // unfortunatly didnt find how to do it
// for some reasons i dont want to do a.group();
group.circle(5,5,5);
a.add(group);
Here is what I did :
var a = Snap("#id");
s = Snap(); // creates a SVG element instead of a group
s.circle(5,5,5);
a.add(s);
It works, the circle is rendered, but then I cannot move the group :
s.attr({"x":60}); // the group doesnt move
Actually it looks like that when we embed and <svg> elements into an other one. Then it becomes impossible to move the embeded svg element in the parent one.
I would like to know how to create a group element without doing snapInstance.group() ? And then add it to a Snap instance.
I'm still not quite sure from your description what you are after, as I suspect it may depend how you are generating the original group (if its just a bit of svg markup or imported).
Snap.parse('<g></g>'); may be enough to fiddle with, to parse into a fragment.
See if this helps...its an example with two separate SVG elements and Snap instances. It will draw a rect from the original SVG markup string with a group,add a circle from Snap, and on the 2nd instance it will translate the group by 75 as well.
<svg id="svg1" width="200" height="200"></svg><br />
<svg id="svg2" width="200" height="200"></svg>
...
var paper1 = Snap("#svg1");
var paper2 = Snap("#svg2");
var groupMarkup = '<g><rect x="0" y="0" width="70" height="70" opacity="0.3"/><text x="0" y="15">original</text></g>';
var parsedMarkup1 = Snap.parse( groupMarkup ); //parse from a string derived elsewhere
var parsedMarkup2 = Snap.parse( groupMarkup );
// example1 just use the markup with its original group
paper1.add( parsedMarkup1 )
.add( paper1.circle(100,50,50)
.attr('fill', 'red' ) );
// example2, will create a new group and add the existing group to it, and then move it
var outerG = paper2.g()
.transform('t75,0'); //create a group and move it
outerG.add( parsedMarkup2 ); //add the original group/square
outerG.add( paper2.circle(70,50,50) //add a circle
.attr('fill', 'blue' ) );
var clone = outerG.clone(); //lets create a clone
clone.transform('r45t50,50'); //translate and rotate the clone
fiddle here http://jsfiddle.net/v4bJa/

Categories