Get the current matrix transformation of an SVG element - javascript

I know a very easy way to get the current matrix transformation of any SVG element:
// 't' is a string
var t = window.getComputedStyle(nativeElement, null).transform
console.log(t);
The problem is that the previous method returns numbers with no more than six decimals. For example, the previous code may return:
matrix(0.965926, 0.258819, -0.258819, 0.965926, 0, 0)
Is there a way to get the matrix transformation of any SVG element more accurately?

To get the current transform attribute as an SVGMatrix object, you can use:
element.transform.baseVal.consolidate().matrix
var myrect = document.getElementById("myrect");
console.log(myrect.transform.baseVal.consolidate().matrix);
<svg>
<rect id="myrect" width="10" height="10" transform="scale(2) rotate(45)"/>
</svg>

Consolidation can change your element 'transform' attribute value.
You can also get a matrix without changing the transformation attribute by transforming the element matrix to the parent.
See documentation about the:
getTransformToElement
function getMatrix(element) {
var matrix = element.parentNode
.getScreenCTM()
.inverse()
.multiply(element.getScreenCTM());
return matrix;
}
var myrect = document.getElementById("myrect");
console.log(getMatrix(myrect));
<svg>
<rect id="myrect" width="10" height="10" transform="scale(2) rotate(45)"/>
</svg>

In the case if you know that your SVG element has no ancestors wich were transformed you can use SVGelement.getCTM() function for it because it is shorter. I think that CTM in the function name is the short form from «current transformation matrix».
var rect = document.querySelector("#rect");
console.log(rect.getCTM());
<svg>
<rect id="rect" width="10" height="10" transform="scale(2) rotate(45)"/>
</svg>
Difference rect.getCTM() vs. rect.transform.baseVal.consolidate().matrix
But you should be careful about the use from this function because it only gives the same result like from the matrix rect.transform.baseVal.consolidate().matrixas long as no ancestor elements have a transform. For example:
var rect = document.querySelector("#rect"),
ctmMatrix = rect.getCTM(),
baseValMatrix = rect.transform.baseVal.consolidate().matrix;
console.log('CTM Matrix: translateX = '+ctmMatrix.e+', translateY = '+ctmMatrix.f);
console.log('BaseVal Matrix: translateX = '+baseValMatrix.e+', translateY = '+baseValMatrix.f);
<svg>
<g transform="translate(35,45)">
<rect id="rect" width="10" height="10" transform="translate(35,45)"/>
</g>
</svg>
I thank #PaulLeBeau for the explanation about the difference between this matrixes.

Related

Change Position of svg element using JS

Trying to make an svg rectangle that moves when button pushed. Right now I just want the x to be modified by a function.
function modX()
{
document.getElementById("rectangle").transform = 'translate(295 115)';
}
var x = 20;
var y = 20;
modX();
<svg width="1000" height="1000" >
<rect id="rectangle" x="0" y="20" width="100" height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)"></rect>
</svg>
I'm fairly new to code so please avoid css or jquery.
you can change its x by using javaScript document.getElementById("rectangle").setAttribute('x', X_value)
set the X_value to the value you want it to change.

Snap SVG: String to Element

In jQuery you can simply creating an element by providing a string, like so:
var newElement = $('<div></div>');
How can I do the same thing in Snap SVG? I have a string like
<rect x="100" y="100" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 1825.4047 1024.3746)" fill="#7EC242" width="230.02" height="56.723" stroke="#64bc46"/>
And I need an Element I can append to an already existing Snap document. I tried fragments, but they don't have all functions I need to manipulate the element afterwards.
I believe you can do it with parse (I removed the transform so the code could work in the small SO snippet window):
var s = Snap("#svg");
var string = '<rect x="100" y="100" fill="#7EC242" width="230.02" height="56.723" stroke="#64bc46"/>'
var rect = Snap.parse(string);
s.append(rect);
<script src="http://cdn.jsdelivr.net/snap.svg/0.1.0/snap.svg-min.js"></script>
<svg id="svg" width="400" height="200">
</svg>

how to scale the element created by use by keeping the fixed position in svg

I want to scale the element created by use by keeping the fixed position in svg.
I read this
but my element is created by use
so it shows
Simply I can remove the old one and create a new one ,but I feel this a bit trouble.
So I wonder whether it exists any convenient way?
function tableBindMouseClick(parametersObject)
{
var table = document.getElementById("PointsTable");
var length = $('#PointsTable tbody tr').length;//get table rows number
for(var i =0;i<length;i++)
{
var id = i;
$($('#PointsTable tbody tr')[i]).bind('click',
(function(id)
{
return function()
{
var p = parametersObject.pointArray[id];
var x = p[0] -5;//coordinate x
var y = p[1] -5;//coordinate y
var icon = document.getElementById("point"+id);
icon.setAttributeNS(null, "transform", "translate("+-x+"," + -y +") scale(3) translate("+x+","+y+")");
};
})(id));
}
I do not know whether it is enough.
I am still modifying it.It can run but its effect is still incorrect.
The result
I can not see the error...
PS:Unfortunately,I use the defs element instead of symbol element to create icon.I also want to know difference in them,including g element.
I complete it by this parameters:
icon.setAttributeNS(null, "transform", "translate("+-2*x+"," + -2*y +")" + " scale(3)" );
I think the post makes some mistakes...
This example may make sense.
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Scalable Vector Graphics (SVG) 1.1 (Second Edition)</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" width="5000" height="5000" viewBox="0 0 5000 5000">
<rect x="100" y="100" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
<rect x="100" y="100" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"
transform ="translate(-230,-230 ) scale(3)" />
</svg>
</body>
</html>

Get absolute coordinates of SVG path with Javascript

I am creating a program which converts a SVG file to my own format. I have created a web based application to do this. I use the default DOM parsing functionality of web browsers to iterate over the SVG contents.
With Javascript I can get a SVG path element using:
var path = document.getElementById("path3388");
I can get the path segments using:
var pathSegments = path.pathSegList
However these path segments are relative to whatever parent SVG element is defined. Transforms are not included in the path segment list.
Is there a way to get the absolute coordinates of this path as they are ultimately used when drawn on the screen?
Example: say I got the following SVG snippet:
<g transform="translate(100, 100)">
<g transform="translate(50, 50)">
<path d="M 0,0 10,0 10,10"></path>
</g>
</g>
What I want is to retrieve is the coordinates of the path with the transforms of the two g elements applied. In this case the coordinates of the path should be:
[150,150], [160, 150], [160, 160]
You want is to do something like this to each path segment coordinate...
var root = document.getElementById("root");
var path = document.getElementById("path");
var point = root.createSVGPoint();
point.x = 0; // replace this with the x co-ordinate of the path segment
point.y = 0; // replace this with the y co-ordinate of the path segment
var matrix = path.getTransformToElement(root);
var position = point.matrixTransform(matrix);
alert(position.x + ", " + position.y);
<svg id="root">
<g transform="translate(100, 100)">
<g transform="translate(50, 50)">
<path id="path" d="M 0,0 10,0 10,10"></path>
</g>
</g>
</svg>
If you find that there's no getTransformToElement function any more since it's been removed in SVG 2 then this polyfill will restore that missing method.
path.getTransformToElement() is no longer supported in Chrome as of v48.
A slightly simpler method might entail...
const path = document.getElementById("path");
const pathBBox = path.getBBox();
console.log(pathBBox.x, pathBBox.y);

How do I get the width of a scaled SVG element with JavaScript?

If I have inline SVG, including an element which has been scaled...
<g transform="scale(sX,sY)">
<rect id="myElement" x="107" y="32" width="245" height="31" stroke="#C6C3C6" stroke-width="1px" />
</g>
... or which is in a <svg> element with a viewBox attribute:
<svg viewBox="20 20 5000 1230">
<g transform="scale(sX,sY)">
<rect id="myElement" x="107" y="32" width="245" height="31" stroke="#C6C3C6" stroke-width="1px" />
</g>
<svg>
... how can I programmatically find the new scaled width in pixels of myElement - without manually detecting the scaling and doing the math? So far myElement.getBBox().width returns 245 without accounting for the scaling.
please check this fiddle http://jsfiddle.net/T723E/. Click on the rectangles and note the firebug console.
Here i have hard coded a number .3 which is 300px width of div containing svg node / 1000 user units.
After seeing the bounty, this is the function i have return to get the scaled width without much (with no maths i'm not sure.)maths.Use matrix.d for getting scaled height
var svg = document.getElementById('svg');
function getTransformedWidth(el){
var matrix = el.getTransformToElement(svg);
return matrix.a*el.width.animVal.value;
}
var ele = document.getElementById('myElement_with_scale')
console.log("scale width----", getTransformedWidth(ele))
Please look this fiddle for complete code http://jsfiddle.net/b4KXr/
Have you investigated the parameter you can use with getBBox()?
http://raphaeljs.com/reference.html#Element.getBBox

Categories