NVD3堆积面积图

时间:2014-02-20 19:07:32

标签: d3.js nvd3.js stacked-area-chart

堆积面积图示例http://nvd3.org/ghpages/stackedArea.html

当我点击一个系列时,它会扩展到所有图表区域,删除其他系列。 如何禁用此功能?

3 个答案:

答案 0 :(得分:6)

没有任何NVD3图表选项可以覆盖此行为,但您可以直接覆盖click事件处理程序。但是,堆积区域图表有点复杂......

NVD3使用d3.dispatch对象来处理自定义事件。用户点击和鼠标悬停以及相关操作都将转换为这些自定义事件。

如果希望在自定义事件之后发生函数,则可以调用调度对象的.on(eventName, function)方法。如果函数参数为null,则它会取消附加到该名称的任何先前的事件处理函数。 (如果您希望同一事件触发多个函数,可以使用"eventName.namespace"形式的字符串作为第一个参数,在事件名称中添加“名称空间”;只有当该函数被取消时才会被取消使用完全相同的事件名称字符串再次调用on。)

因此,要取消您不想要的行为,您需要检查源代码以找出触发该行为的自定义事件的名称,并使用该方法调用调度对象的on方法name和null函数。

这是复杂的地方。实际上有多个不同的事件导致数据系列被打开和关闭。如果单击该区域,如果单击图例,或者单击鼠标悬停时出现的散点图圆之一,则会得到相同的行为。因此,所有这些事件都必须覆盖。它们甚至不是同一个调度对象的所有部分:主图表对象本身有一个调度对象,它处理通过单击图表布局控件创建的完整重绘事件,但堆叠区域上的点击事件由内部处理绘制绘图区域的图表功能,散点图上的点击事件由其中的内部图表功能处理,图例上的点击事件在图例功能中处理。

这就是真正复杂的地方。当整个图表更新或其布局发生变化时,绘图区域和散点图的内部图表绘制功能将被主图表功能覆盖。这意味着所有事件都会重置为NVD3默认值。

因此,您不仅必须禁用触发该行为的所有事件,还必须修改更新功能以再次禁用它们。并且因为每次更新都会重置更新函数本身,*您需要将更新函数的修改包含在用于禁用事件的函数中。

**更新功能只是使用相同的容器选择重新调用整个图表绘制功能。图表函数的第一行之一创建更新函数。*

以下是代码,基于nvd3.org live code page上的Stacked Area示例:

nv.addGraph(function() {

  /* Set up chart as normal */
  var chart = nv.models.stackedAreaChart()
                .x(function(d) { return d[0] })
                .y(function(d) { return d[1] })
                .clipEdge(true)
                //.useInteractiveGuideline(true)
      ;

  chart.xAxis
      .showMaxMin(false)
      .tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });

  chart.yAxis
      .tickFormat(d3.format(',.2f'));

  d3.select('#chart svg')
    .datum(data)
      .transition().duration(500).call(chart);

  /* create a function to disable events and modify the update function */
  function disableAreaClick() {

    //I'm probably over-killing with the amount of events I'm cancelling out
    //but it doesn't seem to have any side effects:
    chart.stacked.dispatch.on("areaClick", null);
    chart.stacked.dispatch.on("areaClick.toggle", null);

    chart.stacked.scatter.dispatch.on("elementClick", null);
    chart.stacked.scatter.dispatch.on("elementClick.area", null);

    chart.legend.dispatch.on("legendClick", null);
    chart.legend.dispatch.on("legendDblclick", null);
    chart.legend.dispatch.on("stateChange", null);

    if (chart.update) {
       //if the chart currently has an update function
       //(created when the chart is called on a container selection)
       //then modify it to re-call this function after update

       var originalUpdate = chart.update; 
           //assign the update function to a new name

       chart.update = function(){
          originalUpdate();
          disableAreaClick();
       }
    }
  } 

  //Call your function, disabling events on current chart and future updates:
  disableAreaClick();
  //this must be called *after* calling the chart on a selection
  //so that it has an update function to modify

  nv.utils.windowResize( chart.update );

  return chart;
});

答案 1 :(得分:0)

您现在可以做的最好的事情是禁用图例。 您可以使用chart.showLegend(false)执行此操作,或者选择以下选项:

var options = {
    showLegend: false
};

答案 2 :(得分:0)

如果你不介意不响应任何鼠标事件,这是一个讨厌的解决方案:

pointer-events: none;

在元素上使用它。