How can I specify a custom XML/SVG namespace with D3.js? - svg

I am trying to define my own namespace inside a SVG so I can use my own tags and attributes. If I understand correctly, the SVG should look like this:
<svg xmlns:myns="http://www.example.com/whatever/">
<g myns:mycustomattr="123">
...
I am adding root SVG element through D3, but adding a namespace to it with attr fails:
var svg = d3.select("#container")
.append("svg")
.attr('xmlns:myns', 'http://www.example.com/whatever/')
The code above results in: NamespaceError: An attempt was made to create or change an object in a way which is incorrect with regard to namespaces
What would be the correct way to add namespace to SVG using D3.js?

You just set d3.ns.prefix
d3.ns.prefix.myns = "http://www.example.com/whatever/";
Then use it:
var svg = d3.select("#container")
.append("svg")
.attr('myns:someAttribute', 'some value');

Related

How do I save an svg node to a file using nodejs?

I'm using d3 through a small helper package: https://www.npmjs.com/package/d3-node
I created my svg file using d3-node, here's the code.
const D3Node = require('d3-node')
var d3n = new D3Node()
var svg = d3n.createSVG()
.style("width","1920px")
.style("height","1080px")
.attr("preserveAspectRatio","true")
.html(firstTemplate)
.append("myCustomTag")
Now after this, I have no idea how to save the output. The main problem is in myCustomTag.
console.log(d3n.d3Element.select("svg").node().innerHTML)
This line is supposed to output my svg, and it does, except that myCustomTag becomes mycustomtagand my svg gets corrupt.
I have tried select("svg").node().outerHTML, select("svg").html(), innerText, I just couldn't find anything.
I can't use the innerHTML in this case, is there a way to store the svg file directly from the d3 variable?
You could use xmlserializer since SVG is XML and XML is case sensitive. Something like this works for me:
const D3Node = require('d3-node');
const xmlserializer = require('xmlserializer');
const d3n = new D3Node();
var svg = d3n.createSVG()
.style("width","1920px")
.style("height","1080px")
.attr("preserveAspectRatio","true");
svg.append("myCustomTag");
console.log(xmlserializer.serializeToString(svg.node()));
HTML is not case sensitive so when you try to use HTML methods to serialize things you won't necessarily get what you want.

Get current rotation in degrees of group in snap.svg

how do i get the current rotation in degrees of a element in snap.svg?
I can set a tranform but i find no easy way of getting a value.
A typical group looks like this.
<g transform="matrix(0.5154,0.5154,-0.5154,0.5154,64.3512,5.239)"><text x="0" y="0" style="font-size: 12px;">Change text</text></g>
You can access elements matrices via the transform() function (with no parameters).
That will provide localMatrix which is probably what you want (if there are no nested transforms or anything). Then there is a function split() which will show the different parts of the matrix.
Using your SVG code above, access would look like this.
var g = Snap('g');
var matrixObj = g.transform().localMatrix.split()
alert( matrixObj.rotate );
jsfiddle

How to change an attribute of a nested SVG element without an ID?

I want to change the height of rect
<clipPath xmlns="http://www.w3.org/2000/svg" id="svge-1">
<rect fill="none" x="0" y="0" width="761" height="231" />
</clipPath>
According to this, http://tutorials.jenkov.com/svg/scripting.html#changing-attribute-values, it should be easy but the problem is the rect here does not have an id.
How can I add an id to it or access the height of rect here?
There are several other ways to retrieve the element using DOM.
You can use getElementById('svge-1') to get the parent element, and get the elements named rect using getElementsByTagName in the context of that element. This will give you the first (and only) rect element:
var clipPathElement = document.getElementById("svge-1");
var rectElement = clipPathElement.getElementsByTagName("rect")[0];
You could also use DOM attributes to get the child elements ignoring their name with children. This will give you the first element, which is rect:
var rectElement = clipPathElement.children[0];
You could also use childNodes, but you would have to get the second object(childNodes[1]), since it contains all nodes (not only elements) which includes the whitespace text node before the tag.
From there you can change any attribute you want:
rectElement.setAttribute("height", "100");
Here is a JSFiddle with a working example.

How to get reference to SVG (child) elements nested in another SVG element (parent) using D3?

I have several groups (SVG G elements) nested in another group and I would like to get their ID's. I used the D3 javascript library to create the SVG and the code looks similar to this.
var body = d3.select("body");
var svg = body.append("svg")
.attr("width", '100%')
.attr("height", '100%')
var outerG = svg.append("g")
.attr('id','outerG')
var innerG1 = outerG.append('g')
.attr('id','innerG1')
var innerG2 = outerG.append('g')
.attr('id','innerG2')
I tried to use childNodes attribute, but console.log(outerG[0].childNodes) gives me undefined. Could not find the right answer searching with google, could please someone give me a hint how to do that ?
This will work:
console.log(outerG[0][0].childNodes);
See jsFiddle here
The reason you need two nested indices is that all selections are grouped implicitly. If you'd like to know the deeper reasons for this, or want to understand selections better in general, see this article

How to get width of imported svg file using fabricjs

I am importing an svg from Corel ... the Corel stage is huge, about 3000x3000px. The svg created by Corel includes the w/h of the stage in the <svg> element:
<svg ... width="2479px" height="3504px" ... >
I import that svg into html via fabricjs:
$("#loadSVG")
.click( function()
{ fabric.loadSVGFromURL( gvs_svgSrc ,
function( A , B ){ callback( A , B ) } ,
function( M , N ){ reviver ( M , N ) }
);
});
Now I would like to scale my fabric objects according to the relationship between my canvas w/h vs the svg w/h.
QUESTION: how can I get the <svg> w/h attributes using fabricjs?
NOTE: I suppose I could do this with javascript/jquery, but I would like to think that fabric already has this information stored in it.
NOTE: I should mention that the vector shapes coming from Corel are broken up into many different groups inside fabric's reviver function. In other words they are not all in ONE group (which would allow me to query the group's w/h.
In your callback function (the second argument), B is an object with the svg canvas width and height properties.

Resources