- Jump To … +
  butterfly_example.ts flamechart_sunburst_example.ts legend_example.ts pie_example.ts plot_area_example.ts plot_zoom_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

- # swimlanes_example.ts

- ¶

  ## C3 Swimlane Timelines

  Demonstrate how to create timelines with swimlanes.

      type SwimlaneDatum = {
          swimlane: number
          time: number
          duration: number
          color: string
      }

- ¶

  ## Prepare the Segment Data

  A function to generate random swimlane data

      function generate_segment_data(data: SwimlaneDatum[]) {
          data.length = 0;
          let color_scale = d3.scale.category10();
          let color = color_scale('seed');
          for (let swimlane = 0; swimlane < 4; swimlane++)
              for (let time = Math.random()*5; time < 100; time += Math.random() * 15) {
                  let duration = Math.random() * 15;
                  if (Math.random() > 0.75)
                      color = color_scale(Math.random().toString());
                  data.push({
                      swimlane: swimlane,
                      time: time,
                      duration: time + duration > 100 ? 100 - time : duration,
                      color: color,
                  });
                  time += duration;
              }
          c3.array.sort_up(data, (d) => d.time);
      }

- ¶

  ## Create the Segment Swimlane Chart

- ¶

  Create a `c3.Plot` chart.

      var segment_layer: c3.Plot.Layer.Swimlane.Segment<SwimlaneDatum>;
      var swimlane_timeline = new c3.Plot.Zoomable<SwimlaneDatum>({
          anchor: '#swimlanes_segment_plot',
          width: '95%',
          height: 300,
          zoomable: 'h',

          data: [],

- ¶

  Setup the scales to go from 0-100 horizontally and 4 swimlanes vertically.

          h: d3.scale.linear().domain([0, 100]),
          v: d3.scale.linear().domain([0, 4]),

- ¶

  Add an x axis with grid lines.

          axes: [
              new c3.Axis.X({
                  grid: true,
                  ticks: false,
              }),
          ],

          layers: [

- ¶

  Add a segment swimlane layer

              segment_layer = new c3.Plot.Layer.Swimlane.Segment<SwimlaneDatum>({

- ¶

  Accessor functions which describe how to get x, dx and y values from the data elements.

                  x: (d) => d.time,
                  dx: (d) => d.duration,
                  y: (d) => d.swimlane,

                  rect_options: {

- ¶

  Static styles are more efficiently handled in a CSS file, this is just an example.

                      styles: {
                          'fill': (d) => d.color,
                          'stroke': (d) => d3.rgb(d.color).darker().toString(),
                          'stroke-width': 2,
                          'rx': 5, // rounded corners (Doesn't work in IE11)
                          'shape-rendering': 'geometricPrecision',
                      },
                  },

- ¶

  Create lables for each segment

                  label_options: {
                      text: (d) => Math.round(d.duration),
                      styles: {
                          'font-weight': 'bold',
                          'text-shadow': (d)=> '1px 1px 1px '+d3.rgb(d.color).brighter().toString(),
                      },
                  },

- ¶

  An HTML tooltip

                  hover: (d) => d ? Math.round(d.duration) : null,

- ¶

  Add a border between swimlanes

                  lane_options: {
                      styles: {
                          'fill': 'none',
                          'stroke': 'gray',
                      },
                  },
              }),
          ],
      });

- ¶

  ## Create the Sampled Swimlane Charts

- ¶

  Create a `c3.Plot` chart.

      var sampled_svg_timeline = new c3.Plot.Zoomable<SwimlaneDatum>({
          anchor: '#swimlanes_sampled_svg_plot',
          width: '95%',
          height: 300,
          zoomable: 'h',

          data: [],

- ¶

  Setup the scales to go from 0-100 horizontally and 4 swimlanes vertically.

          h: d3.scale.linear().domain([0, 100]),
          v: d3.scale.linear().domain([0, 4]),

- ¶

  Add an x axis with grid lines.

          axes: [
              new c3.Axis.X({
                  grid: true,
                  ticks: false,
              }),
          ],

          margins: { bottom: 20 },

          layers: [

- ¶

  Add a sampled swimlane layer

              new c3.Plot.Layer.Swimlane.Sampled.SVG<SwimlaneDatum>({

- ¶

  Accessor functions which describe how to get x, dx and y values from the data elements.

                  x: (d) => d.time,
                  dx: (d) => d.duration,
                  y: (d) => d.swimlane,

                  line_options: {
                      title: (d) => Math.round(d.duration),
                      styles: {
                          'stroke': (d) => d.color,
                      },
                  },

- ¶

  Add a border between swimlanes

                  lane_options: {
                      styles: {
                          'fill': 'none',
                          'stroke': 'gray',
                      },
                  },
              }),
          ],
      });

      var sampled_canvas_timeline = new c3.Plot.Zoomable<SwimlaneDatum>({
          anchor: '#swimlanes_sampled_canvas_plot',
          width: '95%',
          height: 300,
          zoomable: 'h',

          data: [],

- ¶

  Setup the scales to go from 0-100 horizontally and 4 swimlanes vertically.

          h: d3.scale.linear().domain([0, 100]),
          v: d3.scale.linear().domain([0, 4]),

- ¶

  Add an x axis with grid lines.

          axes: [
              new c3.Axis.X({
                  grid: true,
                  ticks: false,
              }),
          ],

          layers: [

- ¶

  Add a sampled swimlane layer

              new c3.Plot.Layer.Swimlane.Sampled.Canvas<SwimlaneDatum>({

- ¶

  Accessor functions which describe how to get x, dx and y values from the data elements.

                  x: (d) => d.time,
                  dx: (d) => d.duration,
                  y: (d) => d.swimlane,
                  safe: false,

                  line_options: {
                      styles: {
                          'stroke': (d) => d.color,
                      },
                  },

- ¶

  Add a border between swimlanes

                  lane_options: {
                      styles: {
                          'fill': 'none',
                          'stroke': 'gray',
                      },
                  },

- ¶

  HTML tooltip

                  hover: (d) => d ? Math.round(d.duration) : null,
              }),
          ],
      });

- ¶

  ## Render the Charts

- ¶

  Generate initial data

      generate_segment_data(swimlane_timeline.data);
      sampled_svg_timeline.data = swimlane_timeline.data;
      sampled_canvas_timeline.data = swimlane_timeline.data;

- ¶

  Call `render()` on the charts to initially render them.

      swimlane_timeline.render();
      sampled_svg_timeline.render();
      sampled_canvas_timeline.render();

- ¶

  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_segment_data(swimlane_timeline.data);
          swimlane_timeline.redraw();
          sampled_svg_timeline.redraw();
          sampled_canvas_timeline.redraw();
      });

- ¶

  Set the chart to limit the number of segments rendered. Note that it will prioritize drawing the longest segments first.

      $('#limit_segments').on('change', function () {
          if (this.checked) {
              $('#limit_segment_count').prop('disabled', false);
              segment_layer.limit_elements = +$('#limit_segment_count').val();
          } else {
              $('#limit_segment_count').prop('disabled', true);
              segment_layer.limit_elements = null;
          }
          swimlane_timeline.redraw();
      });

- ¶

  Adjust the number of elements to limit as the slider is changed. The `input` event not supported in IE

      for (var event_name of ['input', 'change']) {
          $('#limit_segment_count').on(event_name, function () {
              segment_layer.limit_elements = +$(this).val();
              swimlane_timeline.redraw();
          });
      }

- ¶

  Resize the chart to fit the window

      window.onresize = () => {
          swimlane_timeline.resize();
          sampled_svg_timeline.resize();
          sampled_canvas_timeline.resize();
      }