aroaro
aroaro

Reputation: 273

D3.js: making a circle which is itself made up of rectangles, in SVG

I'm quite new to d3/SVG, and I'm trying to make something slightly complex. Here's an example of the shape I'm trying to draw:
stripey circle

Any ideas about how I could achieve this? I've been fiddling around with pattern fills without much luck. Or, it's easy to create a rectangle of bars, do I do that and then use it as a fill for the circle? Or, is it a matter of creating six different shapes with the relevant arcs.
Any pointers are appreciated.

Upvotes: 2

Views: 668

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38221

The easiest way may be to simply append rectangles (as you note this is fairly easy) but add a clip path. This will keep things simple for appending rectangles and allow you to change the clip path if you want to change your radius or shape (without having to update each rectangle):

svg = d3.select('body')
   .append('svg')
   .attr('width',500)
   .attr('height',500);
   
color = d3.schemeCategory20;
   
circle = svg.append('circle')
  .attr('cx',250)
  .attr('cy',250)
  .attr('r',150)
  .attr('fill','none')
  .attr('id','clipper');
  
clipPath = svg.append('clipPath')
    .attr('id',"clip")
      .append("use")
    .attr("xlink:href","#clipper");
    
rects = svg.selectAll('rect')
    .data(d3.range(20))
    .enter()
    .append('rect')
    .attr('x',function(d,i) { return i * 25 })
    .attr('y',0)
    .attr('width',25)
    .attr('height',500)
    .attr('fill',function(d,i) { return color[i]; })
    .attr("clip-path","url(#clip)")
    
animate();
    
function animate() {
  svg.select('circle')
    .transition()
    .attr('r',100)
    .duration(1000)
    .transition()
    .attr('r',200)
    .duration(1000)
    .on('end',animate);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>

Edit:

To add your own colors to the rectangles you could specify your own color array:

var width = 300;
var height = 300;

var svg = d3.select('body')
   .append('svg')
   .attr('width',width)
   .attr('height',height);
   
// Use CSS colors
// var color = ["darkgreen","blue","purple","red","orange","yellow"];

// or Use hex colors:
var color = ["#111","#222","#333","#444","#555","#666"];


var n = 6;


var circle = svg.append('circle')
  .attr('cx',width/2)
  .attr('cy',height/2)
  .attr('r',width/2)
  .attr('fill','none')
  .attr('id','clipper');
  
var clipPath = svg.append('clipPath')
    .attr('id',"clip")
      .append("use")
    .attr("xlink:href","#clipper");
    
var rects = svg.selectAll('rect')
    .data(d3.range(n))
    .enter()
    .append('rect')
    .attr('x',function(d,i) { return i * width / n })
    .attr('y',0)
    .attr('width',width/n)
    .attr('height',500)
    .attr('fill',function(d,i) { return color[i]; })
    .attr("clip-path","url(#clip)")
    
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>

The above snippet will append a specified number of rectangles across the circle (n in the code), and will append colors to them from the array. In the original example, d3.schemeCategory20 is just an array. The i in the inline function function (d,i) will return the element increment which is why an array works easily in getting a fill color.

Upvotes: 3

Related Questions