Modify Donut Chart Slices in C3/D3

為{幸葍}努か 提交于 2019-12-06 03:24:00

You can use setTimeout() to scale specific slices, once the chart is rendered. Here's one way:

setTimeout( function() {
  d3.selectAll('.c3-arc-A, .c3-arc-B, .c3-arc-C').attr("transform", "scale(1.2)");       
}, 5);

Place this call after your c3.generate() call.

miir

c3js has two options, but both require a slight hack with 'setTimeout' to force our default scaling to happen after rendering and animation occur.

  1. The onrendered function is available to set within the c3config object that one initializes the chart with. This function is triggered after a redraw is triggered but before visual rendering happens in the DOM. However, there is a hack to use setTimeout since it will create a separate callstack that will execute after the current callstack which in c3 happens to include redrawing the graph. (explanation of setTimeout to force logic to run after current callstack executes)

  2. The load function exposes a done callback that is triggered after the elements are rendered to the DOM but before the animation finishes. So if one sets the initial scale transform in done, if the animations triggered by load are using the scale transform (which loading a pie chart appears to do), then the last keyframe of the animation will overwrite your modified scale back to scale(1). However, we can similarly use setTimeout to run our code after the current callstack (which includes animation) executes.

In exploring this, I created a generalized form of rby's answer, and I offer two alternative paths to setting default scales through the onrendered and done functions exposed in c3. (Fiddle):

var selected = ['A', 'B', 'C'];
var _ARC = '.c3-arc';
var _SCALING = '1.1';

function getCurrentlySelected() {
  var _PREFIX = _ARC + '-';
  return d3.selectAll(_PREFIX + selected.join(', ' + _PREFIX));
}

Within c3config object and onrendered through initialization:

var chart = c3.generate({
    bindto: '#chart',
    data: { ... },
    onrendered: function() {
        setTimeout(function() {
          if (selected.length > 0) {
            getCurrentlySelected().attr('transform', 'scale(' + _SCALING + ')');
          }
        }); // Notice we don't need a delay, just taking advantage to force our logic to happen after current callstack is executed
    }
});

Also possible to use load with done after initialization:

chart.load({
  columns: [
    ['A', 30, 200, 100, 400, 150, 250],
    ['B', 130, 100, 140, 200, 150, 50],
    ['C', 50, 100, 130, 240, 200, 150],
    ['D', 130, 100, 140, 200, 150, 50],
    ['E', 130, 150, 200, 300, 200, 100]
  ],
  done: function() {
    setTimeout(function() {
      if (selected.length > 0) {
        getCurrentlySelected().attr('transform', 'scale(' + _SCALING + ')');
      }
    }) // Notice we don't need a delay, just taking advantage to force our logic to happen after current callstack is executed
  }
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!