• Jump To … +
    butterfly_example.ts dark_example.ts flamechart_example.ts icicle_sunburst_example.ts legend_example.ts pie_example.ts plot_area_example.ts plot_zoom_example.ts region_example.ts sankey_example.ts scatterplot_example.ts stack_example.ts swimlanes_example.ts sync_example.ts table_searchable_example.ts table_selectable_example.ts table_sortable_example.ts timeline_example.ts worldbank_example.ts
  • ¶

    C3 Pie Charts

    Demonstrate Pie charts.

  • ¶

    Prepare the Data

    A function to generate random data. Construct an array which contains objects that have x and y members.

    type PolarPlotDatum = { id: number, value: number, radius: number, height: number, color:string }
    var random_polar_data: PolarPlotDatum[] = [];
    var radial_line_values = [0.25, 0.666];
    
    var polar_data_color = d3.scale.category10();
    function generate_polar_data() {
        random_polar_data.length = 0;
        for (let i = 0; i < 10; i++) {
            random_polar_data.push({
                id: i,
                value: 10 * Math.random(),
                radius: 7 * Math.random(),
                height: 3 * Math.random(),
                color: polar_data_color(i.toString()).toString(),
            });
        }
    }
  • ¶

    Generate initial dataset.

    generate_polar_data();
  • ¶

    Create a Pie Chart

    var pie_chart_layer: c3.Polar.Layer.Pie<PolarPlotDatum>;
    var pie_chart = new c3.Polar<PolarPlotDatum>({
        anchor: '#pie_example_chart',
        width: 300,
        height: 300,
    
        data: random_polar_data,
  • ¶

    Create a single pie chart layer

        layers: [
            pie_chart_layer = new c3.Polar.Layer.Pie<PolarPlotDatum>({
  • ¶

    A key is necessary for pie charts

                key: (d) => d.id,
                value: (d) => d.value,
                sort: false,
  • ¶

    Set an inner_radius to create a “donut chart” These could also be callbacks

                inner_radius: 0.2,
                outer_radius: 0.8,
                pad: 0.01,
  • ¶

    Style the pie chart arc segments

                arc_options: {
  • ¶

    Tooltip with just the value, and color based on the data

                    title: (d) => d.value,
                    styles: {
                        'fill': (d) => d.color,
                    },
  • ¶

    Enable the segments to animate when data is changed with a redraw

                    animate: true,
                    duration: 4000,
  • ¶

    Have the segments slide out slightly when hovering over them

                    events: {
                        'mouseenter': function () {
                            d3.select(this).transition('grow').attr('transform', 'scale(1.2)');
                        },
                        'mouseleave': function () {
                            d3.select(this).transition('grow').attr('transform', 'scale(1)');
                        },
                    },
                },
  • ¶

    If the data is sorted and the elements are limited, then this creates an arc segment for the range of the other values of the ellided data.

                other_options: {
                    title: (d) => "Other",
                    styles: {
                        'fill': 'black',
                        'opacity': 0.5,
                        'stroke': 'black',
                        'stroke-width': 2,
                        'stroke-dasharray': '5,5',
                    },
                    animate: true,
                },
            }),
        ],
    }).render();
  • ¶

    Create a Polar Segment Chart

    var polar_segment_chart = new c3.Polar<PolarPlotDatum>({
        anchor: '#polar_segment_example_chart',
        width: 300,
        height: 300,
  • ¶

    Use the same data array for this layer

        data: random_polar_data,
  • ¶

    Setup angular and radial scales to go from 0-10

        t: d3.scale.linear().domain([0, 10]),
        r: d3.scale.linear().domain([0, 10]),
        zoomable: true,
    
        layers: [
  • ¶

    Create a single Arc segment layer

            new c3.Polar.Layer.Arc<PolarPlotDatum>({
                key: (d) => d.id,
                value: (d) => d.value,
  • ¶

    Arc segments layers can define the radius and angle extents of the segment region.

                inner_radius: (d) => d.radius,
                outer_radius: (d) => d.radius + d.height,
                start_angle: (d) => d.id,
                end_angle: (d) => d.id + (d.value / 5),
  • ¶

    Style and animate the arc segments

                arc_options: {
                    title: (d) => d.value,
                    styles: {
                        'fill': (d) => d.color,
                    },
                    animate: true,
                    duration: 4000,
                },
            }),
        ],
    }).render();
  • ¶

    Create a Half-moon Pie Chart

    var half_moon_chart = new c3.Polar<PolarPlotDatum>({
        anchor: '#half_moon_example_chart',
        width: 600,
        height: 600,
    
        data: random_polar_data,
  • ¶

    Setup the angular range from -π/2 to π/2 to create a “half moon” effect.

        angular_range: [-Math.PI/2, Math.PI/2],
        zoomable: true,
    
        layers: [
            new c3.Polar.Layer.Pie<PolarPlotDatum>({
                key: (d) => d.id,
                value: (d) => d.value,
                sort: false,
  • ¶

    Create a half-ring with these radius

                inner_radius: 0.6,
                outer_radius: 0.9,
                pad: 0.015,
    
                arc_options: {
  • ¶

    Style the arc segments

                    title: (d) => d.value,
                    styles: {
                        'fill': (d) => d.color,
                    },
  • ¶

    Animate arc segments when they move due to redraw()

                    animate: true,
                    duration: 4000,
  • ¶

    Animate arc segments sliding out when hovering just for fun.

                    events: {
                        'mouseenter': function () {
                            d3.select(this).transition().attr('transform', 'scale(1.1)');
                        },
                        'mouseleave': function () {
                            d3.select(this).transition().attr('transform', 'scale(1)');
                        },
                    },
                },
  • ¶

    Create an arch segment for “other” data that was decimated due to sorting and limiting the segment count with limit_elements and sort.

                other_options: {
                    title: (d) => "Other",
                    styles: {
                        'fill': 'black',
                        'opacity': 0.5,
                        'stroke': 'black',
                        'stroke-width': 2,
                        'stroke-dasharray': '5,5',
                    },
                    animate: true,
                },
            }),
  • ¶

    Create a second layer to demonstrate composability. This layer is just a thin band of three segments

            new c3.Polar.Layer.Pie<number>({
                key: (d) => d,
                value: (d) => d,
                inner_radius: 0.55,
                outer_radius: 0.5,
                pad: 0.015,
    
                data: [3, 2, 1],
  • ¶

    Style the segments to be red, green, and blue respectively.

                arc_options: {
                    title: "Example extra data layer",
                    styles: {
                        'fill': (d,i) => ['red','green','blue'][i],
                    },
                },
            }),
  • ¶

    Create a third layer of radial line vectors.

            new c3.Polar.Layer.Radial<number>({
                value: (d) => d,
  • ¶

    Use a global array for the data so it can be shared with the legend

                data: radial_line_values,
  • ¶

    Allow the lines to be draggable

                draggable: true,
  • ¶

    Draw one vector with an infinite length and the other with the full radius of 1

                outer_radius: (d,i) => i ? 1 : Infinity,
  • ¶

    Style one line in red and the other in green.

                line_options: {
                    styles: {
                        'stroke': (d, i) => ['red','green'][i],
                        'stroke-dasharray': '10,5',
                        'stroke-width': 3,
                    },
                },
    
                handlers: {
  • ¶

    When the lines are dragged, update the original data array and sync with the legend by redrawing it.

                    drag: (value, d, i) => {
                        radial_line_values[i] = value;
                        radial_line_values_legend.redraw();
                    },
  • ¶

    Redraw layer so it binds the updated values. This wouldn’t be necessary if we were just modifying an Object in-place in the data array.

                    dragend: function (value, d, i) { this.redraw(); },
                },
            }),
        ],
    }).render();
  • ¶

    Legend for radial vectors

  • ¶

    Create a legend for the current values of the radial lines

    var radial_line_values_legend = new c3.Legend<number, void>({
        anchor: '#line_values_legend',
    
        data: radial_line_values,
  • ¶

    Display the value as a truncated integer percentage

        item_options: {
            text: (d) => ((d*100)|0)+'%',
        },
  • ¶

    Use a matching colored swatch for the legend bullets

        bullet_options: {
            html: '',
            styles: {
                'background': (d, i) => ['red', 'green'][i],
                'height': '1em',
                'width': '1em',
                'border-radius': '0.25em',
            },
        },
    }).render();
  • ¶

    Forms to modify chart options

  • ¶

    Allow the user generate new data by clicking on a button. We need to redraw() the charts to reflect the updated data. Note: if we had cleared random_data via: random_data = [] in the generate_data() function, then this wouldn’t work. It would just have updated the variable and not the array that the charts are working with. That’s why random_data.length=0 is used.

    $('#sync_generate_button').on('click', () => {
        generate_polar_data();
        pie_chart.redraw();
        half_moon_chart.redraw();
        polar_segment_chart.redraw();
    });
  • ¶

    Enable animations when transitioning datasets

    $('#enable_animations').on('change', function () {
        (<c3.Polar.Layer.Pie<any>>pie_chart.layers[0]).arc_options.animate = this.checked;
        (<c3.Polar.Layer.Pie<any>>half_moon_chart.layers[0]).arc_options.animate = this.checked;
        (<c3.Polar.Layer.Pie<any>>polar_segment_chart.layers[0]).arc_options.animate = this.checked;
    });
  • ¶

    Enable sorting pie wedges

    $('#enable_sorting').on('change', function () {
        (<c3.Polar.Layer.Pie<any>>pie_chart.layers[0]).sort = this.checked;
        pie_chart.redraw();
        (<c3.Polar.Layer.Pie<any>>half_moon_chart.layers[0]).sort = this.checked;
        half_moon_chart.redraw();
    });
  • ¶

    Limit the number of elements that will be drawn. If there are too many elements, then the ones with the smallest value won’t be drawn.

    for (let event_name of ['input', 'change']) { // 'input' event is not supported in IE
        $('#limit_segment_count').on(event_name, function () {
            (<c3.Polar.Layer.Pie<any>>pie_chart.layers[0]).limit_elements = +$(this).val();
            pie_chart.redraw();
            (<c3.Polar.Layer.Pie<any>>half_moon_chart.layers[0]).limit_elements = +$(this).val();
            half_moon_chart.redraw();
            (<c3.Polar.Layer.Arc<any>>polar_segment_chart.layers[0]).limit_elements = +$(this).val();
            polar_segment_chart.redraw();
        });
    }