Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply rotate transformation and don't change the coordinates system in D3.js?

I am rendering dynamically multiple rectangles that have rotate applied to them. What I'm trying to achieve is to put diamond like shapes one below another and isolate the transform attribute. Is it possible?

const svg = d3
  .select('#root')
  .append('g')
  .attr('transform', 'translate(200,200)');

svg.selectAll('.device')
  .data([1, 2, 3, 4])
  .enter()
  .append('rect')
  .attr('width', 10)
  .attr('height', 10)
  .attr('x', 0)
  .attr('y', (d, i) => { return i * 10 * Math.sqrt(2); })
  .attr('transform', 'rotate(45)')
  .attr('fill', '#000');

Here you can find the JSFiddle

Obs. I could resolve this issue by altering the x attribute but I don't want that.

Thank you in advance!

like image 367
Ioan Ungurean Avatar asked Feb 02 '26 08:02

Ioan Ungurean


1 Answers

The issue here has nothing to do with D3. It's an SVG specification: the rotate function of the transform attribute rotates the element around the origin (0,0), not around its center.

There are a couple of solutions here. Since you said that you don't want to change the x attribute, the easiest solution is setting the position in the same transform:

.attr('transform', (d, i) => 'translate(0,' + (i * 10 * Math.sqrt(2)) + ') rotate(45)')
//this is the x attribute---------------^           ^----- and this is the y

Here is your code with that change:

const svg = d3
  .select('#chart')
  .append('g')
  .attr('transform', 'translate(200,50)');

svg.selectAll('.device')
  .data([1, 2, 3, 4])
  .enter()
  .append('rect')
  .attr('width', 10)
  .attr('height', 10)
  .attr('transform', (d, i) => 'translate(0,' + (i * 10 * Math.sqrt(2)) + ') rotate(45)')
  .attr('fill', '#000');
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg id="chart" width="400" height="200"></svg>
like image 151
Gerardo Furtado Avatar answered Feb 03 '26 20:02

Gerardo Furtado