Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert SVG coordinates (x,y) defined relatively to an element into absolute coordinates/position?

I am trying to draw a line, connecting two circles in SVG. The circles are - together with underlying rectangles encapsulated in a SVG group elements (). Those groups are positioned with the transform="translate(x,y)" attributes. My problem is, that the coordinates of the elements inside the group are positioned relatively to the origins (0,0 coordinates) of their groups. To place a overlying line I need to know the absolute coordinates.

Here is the code using the D3 javascript library :

var body = d3.select("body");

var svg = body.append("svg");

var group1 = svg.append("g")
    .attr("transform", "translate(50,50)");

var rect1 = group1.append("svg:rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .style("fill", 'lightblue');

var circ1 = group1.append("svg:circle")
    .attr("cx", 50)
    .attr("cy", 50)
    .attr("r", 10)
    .style("fill", 'red')

var group2 = svg.append("g")
    .attr("transform", "translate(350,50)");

var rect2 = group2.append("svg:rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 100)
    .attr("height", 100)
    .style("fill", 'lightgreen');

var circ2 = group2.append("svg:circle")
    .attr("cx", 50)
    .attr("cy", 50)
    .attr("r", 10)
    .style("fill", 'red');

var line = svg.append("svg:line")
    .attr("x1", parseInt(circ1.attr("cx")))
    .attr("y1", parseInt(circ1.attr("cy")))
    .attr("x2", parseInt(circ2.attr("cx")))
    .attr("y2", parseInt(circ2.attr("cy")))
    .attr("stroke", "black");

I do know why the line does not appear. I also know that every SVG element is related to a transformation-matrix. I am not sure how to access the matrices of the circle-elements and how to get the absolute coordinates of them (the cx/cy attributes). Another possibility would be to get the absolute distance of the circles.

Here is a jsfiddle with the above code

like image 729
karlitos Avatar asked Jun 14 '13 08:06

karlitos


1 Answers

I think I was able to solve the problem myself. The access to the transformation matrix could be achieved using

circ1[0][0].getCTM()

or by using

circ1[0][0].getScreenCTM()

By adding the value of the e attribute to the x coordinate and the value of the f attribute to the y coordinate I was able to get the "absolute position" of the elements.

Updated jsfiddle is here

I am afraid my solution is not universally valid. For example I am not sure what happens in a case I will use transform: scale before the computation of the position ?

like image 186
karlitos Avatar answered Sep 21 '22 16:09

karlitos