ravins
ravins

Reputation: 147

CSS3 - Transform-origin not working on SVG element in d3.js

I've SVG rect element, which I want use for dividing Donut into parts.

But these rectangles(spokes) are not aligned in a straight line.

I'm using D3.js, Please suggest if there is better way to have Spoke wheel effect

Transform Origin on SVG element

rect = wheel.selectAll("g.rect")
  .data(rectData).enter()
  .append("g")
  .attr("transform",function(d,i){
     var rotate = 60*i;
     var rotX = 100, rotY = 150;
     return "translate("+rotX+","+rotY+") rotate("+rotate+")"
  })
  .attr("class","rect");

var width = 200,
  height = 300,
  innerRadius = 100,
  outerRadius = 80;
var wheel = d3.select("#wheel")
  .append("svg")
  .attr("width", width)
  .attr("height", height)

arc = d3.svg.arc()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius)
  .startAngle(0)
  .endAngle(2 * Math.PI)

rectData = [{
  x: width / 2,
  y: height / 2
}, {
  x: width / 2,
  y: height / 2
}, {
  x: width / 2,
  y: height / 2
}, {
  x: width / 2,
  y: height / 2
}, {
  x: width / 2,
  y: height / 2
}, {
  x: width / 2,
  y: height / 2
}]
rect = wheel.selectAll("g.rect")
  .data(rectData).enter()
  .append("g")
  .attr("transform", function(d, i) {
    var rotate = 60 * i;
    var rotX = 100,
      rotY = 150;
    return "translate(" + rotX + "," + rotY + ") rotate(" + rotate + ")"
  })
  .attr("class", "rect");


rect.append("rect")
  .attr("width", 20)
  .attr("height", outerRadius + 10)

wheel.append("path").attr("d", arc)
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
  .attr("class", "donut")
#wheel {
  margin: auto 0;
  width: 300px;
  height: 300px
}
#wheel .donut {
  fill: #F37E36;
}
#wheel rect {
  fill: #A2A931;
  transform-origin: 90 50;
}
#wheel .rect rect {
  transform-origin: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<div id="wheel"></div>

Upvotes: 1

Views: 3004

Answers (1)

jbutler483
jbutler483

Reputation: 24529

here's a simple example of such design (which only uses javascript to calculate the angle).

After simplifying the markup, you would be able to easily add effects to your 'spokes'.

var len = $('.outer').children().length; //gives 4
var angle = 360 / len;
var newAngle = angle;
$('.outer').children().each(function() {
  $(this).css("transform", "rotate(" + newAngle + "deg)");
  newAngle = angle + newAngle;
});
.outer {
  display: inline-block;
  height: 200px;
  width: 200px;
  border: 20px solid tomato;
  border-radius: 50%;
  position: relative;
  z-index: 8;
  transition: all 4s;
}
.spoke {
  position: absolute;
  transform-origin: left center;
  height: 20px;
  width: 50%;
  background: #A2A931;
  left: 50%;
  top: calc(50% - 10px);
  text-align: center;
  z-index: 2;
}
.outer:hover {
  transform: rotate(360deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer">
  <div class="spoke">spoke 1</div>
  <div class="spoke">spoke 2</div>
  <div class="spoke">spoke 3</div>
  <div class="spoke">spoke 4</div>
  <div class="spoke">spoke 5</div>
  <div class="spoke">spoke 6</div>
  <div class="spoke">spoke 7</div>
</div>

Upvotes: 1

Related Questions