Using an arc generator

Among the most common shape generators—besides the line and area generator—D3 also provides the arc generator. At this point, you might be wondering, Didn't SVG standard already include circle element? Isn't that enough?

The simple answer to this is "no". The D3 arc generator is a lot more versatile than the simple svg:circle element. the D3 arc generator is capable of creating not only circles but also annulus (donut-like), circular sector, and annulus sector, all of which we will learn in this recipe. More importantly, an arc generator is designed to generate, as its name suggests, an arc (in others words, not a full circle or even a sector but rather arcs of arbitrary angle).

Getting Ready

Open your local copy of the following file in your web browser:

https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter7/arc.html

How to do it...

In this recipe we will use arc generator to generate multi-slice circle, annulus (donut), circular sectors, and annulus sectors.

<script type="text/javascript">
var width = 400,
height = 400,
// angles are in radians
    fullAngle = 2 * Math.PI, // <-A
    colors = d3.scale.category20c();
    
var svg = d3.select("body").append("svg")
            .attr("class", "pie")
            .attr("height", height)
            .attr("width", width);    

function render(innerRadius, endAngle){
    if(!endAngle) endAngle = fullAngle;

    var data = [ // <-B
        {startAngle: 0, endAngle: 0.1 * endAngle},
        {startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
        {startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
        {startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},        
        {startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},        
        {startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},        
        {startAngle: 0.9 * endAngle, endAngle: endAngle}
    ];
    
    var arc = d3.svg.arc().outerRadius(200) // <-C
                    .innerRadius(innerRadius);
    
    svg.select("g").remove();
    
    svg.append("g")
            .attr("transform", "translate(200,200)")
    .selectAll("path.arc")
            .data(data)
        .enter()
            .append("path")
                .attr("class", "arc")
                .attr("fill", function(d, i){return colors(i);})
                .attr("d", function(d, i){
                   return arc(d, i); // <-D
});
}

render(0);
</script>

<div class="control-group">
    <button onclick="render(0)">Circle</button>
    <button onclick="render(100)">Annulus(Donut)</button>
    <button onclick="render(0, Math.PI)">Circular Sector</button>
    <button onclick="render(100, Math.PI)">Annulus Sector</button>
</div>

The preceding code produces the following circle, which you can change into an arc, a sector, or an arc sector by clicking on the buttons, for example, Annulus(Donut) generates the second shape:

How to do it...

Arc generator

How it works...

The most important part of understanding the D3 arc generator is its data structure. D3 arc generator has very specific requirements when it comes to its data, as shown on line B:

var data = [ // <-B
        {startAngle: 0, endAngle: 0.1 * endAngle},
        {startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
        {startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
        {startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},        
        {startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},        
        {startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},        
        {startAngle: 0.9 * endAngle, endAngle: endAngle}
];

Each row of the arc data has to contain two mandatory fields, startAngle and endAngle. The angles have to be in the range [0, 2 * Math.PI] (see line A). D3 arc generator will use these angles to generate corresponding slices, as shown earlier in this recipe.

Tip

Along with the start and end angles, arc data set can contain any number of additional fields, which can then be accessed in D3 functions to drive other visual representation.

If you are thinking that calculating these angles based on the data you have is going to be a big hassle, you are absolutely correct. This is why D3 provides specific layout manager to help you calculate these angles, and which we will cover in the next chapter. For now, let's focus on understanding the basic mechanism behind the scenes so that when it is time to introduce the layout manager or if you ever need to set the angles manually, you will be well-equipped to do so. D3 arc generator is created using the d3.svg.arc function:

var arc = d3.svg.arc().outerRadius(200) // <-C
                    .innerRadius(innerRadius); 

The d3.svg.arc function optionally has outerRadius and innerRadius settings. When innerRadius is set, the arc generator will produce an image of annulus (donut) instead of a circle. Finally, the D3 arc is also implemented using the svg:path element, and thus similar to the line and area generator, d3.svg.arc generator function can be invoked (see line D) to generate the d formula for the svg:path element:

svg.append("g")
            .attr("transform", "translate(200,200)")
    .selectAll("path.arc")
            .data(data)
        .enter()
            .append("path")
                .attr("class", "arc")
                .attr("fill", function(d, i){return colors(i);})
                .attr("d", function(d, i){
                    return arc(d, i); // <-D
                });

One additional element worth mentioning here is the svg:g element. This element does not define any shape itself, but serves rather as a container element used to group other elements, in this case, the path.arc elements. Transformation applied to the g element is applied to all the child elements while its attributes are also inherited by its child elements.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset