NVD3线性图是否支持标记?

20

我正在制作一张NVD3线性图,如果能为每个数据点显示标记而不仅仅是线本身,将显着提高图表的清晰度。不幸的是,我尚未找到使用NVD3轻松实现此目标的方法。我还考虑使用散点图,但我无法弄清楚如何在点之间显示连接线。第三种选择是将线性图和散点图叠加在一起,但这将在图例中两次显示每个系列,并可能引起其他不必要的视觉问题。

是否有一种优雅的方法来实现这个目标?下面列出了我的格式化技术的示例代码,但是test_data中的'size'和'shape'属性对当前代码的线性图没有影响。

test_data = [ {     key: 'series1',
            values: [
                { x: 1, y: 2.33, size:5, shape:"circle" },
                { x: 2, y: 2.34, size:5, shape:"circle" },
                { x: 3, y: 2.03, size:5, shape:"circle" },
        ] } ];


nv.addGraph(function() {
  var test_chart = nv.models.lineChart();
  test_chart.xAxis.axisLabel('Sample Number');
  test_chart.yAxis
        .axisLabel('Voltage (V)')
        .tickFormat(d3.format('.02f'));

  d3.select('#test_plot')
      .datum(test_data)
    .transition().duration(500)
      .call(test_chart);

  nv.utils.windowResize(test_chart.update);
  return test_chart;
});

有关nvd3版本1.8.6或1.8.4的任何解决方案吗? - Dinesh
5个回答

17

我也想在我正在工作的项目中添加标记。这是我和我的合作伙伴找到的解决方案。

首先,您必须选择图表中的所有点,并将fill-opacity设置为1:

#my-chart .nv-lineChart circle.nv-point
{
    fill-opacity: 1;
}

现在您的点将可见。要调整每个点的大小,请修改每个点的“r”(半径)属性。这不是样式,因此无法使用CSS进行操作。以下是一些jQuery代码可以完成此任务。500毫秒的延迟是为了确保在图表渲染之前代码不会运行。此片段将半径设置为3.5:

        setTimeout(function() {
            $('#my-chart .nv-lineChart circle.nv-point').attr("r", "3.5");
        }, 500);

这也是我所做的,这就是解决方案。 - CQM
然而,如果要更新或重绘该点,则会出现一个问题,即图表首先在屏幕上以不同半径绘制点,然后再以r为3.5并在屏幕上闪烁另一个点。 - Kyleinincubator
我看到源代码中可以为每个数据设置一个大小字段,但是我尝试过了,它并没有起作用,并且有一行代码:Math.sqrt(z(getSize(d,i))/Math.PI) 用于计算r属性。 - Kyleinincubator
这似乎适用于1.8.1版本,但不适用于最新的1.8.4或1.8.6版本。有什么解决办法吗? - Dinesh

11

在社区的帮助下,我才明白了这个问题:

css styling of points in figure

以下是基于 css 的解决方案:

.nv-point {
    stroke-opacity: 1!important;
    stroke-width: 5px!important;
    fill-opacity: 1!important;
}

如果有人从rCharts来到这里,下面是一个rmarkdown模板,可以创建一个包含线条和标记的nPlot

 ```{r 'Figure'}  
require(rCharts)
load("data/df.Rda") 
# round data for rChart tooltip display
df$value <- round(df$value, 2)
n <- nPlot(value ~ Year, group = 'variable', data = df, type = 'lineChart') 
n$yAxis(axisLabel = 'Labor and capital income (% national income)')
n$chart(margin = list(left = 100)) # margin makes room for label
n$yAxis(tickFormat = "#! function(d) {return Math.round(d*100*100)/100 + '%'} !#")
n$xAxis(axisLabel = 'Year')
n$chart(useInteractiveGuideline=TRUE)
n$chart(color = colorPalette)
n$addParams(height = 500, width = 800)
n$setTemplate(afterScript = '<style>
  .nv-point {
    stroke-opacity: 1!important;
    stroke-width: 6px!important;
    fill-opacity: 1!important;
  } 
</style>'
)
n$save('figures/Figure.html', standalone = TRUE)
```

4

当前版本的nvd3使用路径而非圆圈来绘制标记。以下是我用来显示标记的一段CSS代码。

#chart g.nv-scatter g.nv-series-0 path.nv-point
{
    fill-opacity: 1;
    stroke-opacity: 1;
}

我也在https://github.com/novus/nvd3/issues/321中写了一些关于这个的内容,你可以找到我如何改变标记的形状。

我不知道如何改变标记的大小。正在尝试寻找解决方案。


谢谢。我参考了你提到的代码,它帮助我将一个特定的系列转换成散点图。但是我无法改变形状。我正在使用angularjs,并使用angular-nvd3指令-https://github.com/krispo/angular-nvd3/issues/44 - Anand

2

对于当前版本的NVD3(1.8.x),我使用这个基于D3的解决方案(仅使用脚本,不需要CSS文件或样式块):

nv.addGraph(function() {
  // ...
  return chart;
},
function() {
  // this function is called after the chart is added to document
  d3.selectAll('#myChart .nv-lineChart .nv-point').style("stroke-width",
    "7px").style("fill-opacity", ".95").style("stroke-opacity", ".95");
}
);

使用的样式正是NVD3通过将“hover”类应用于每个点(悬停时)添加的样式。根据您的需要进行调整。


我在上面实现了这个解决方案,但我不确定为什么我的回调函数会在图表绘制前被调用。 - Dinesh
@Dinesh 这个函数是在图表被添加到文档后调用的(正如内联注释所说),而不一定是在绘制完成后。你遇到了什么(不想要的)效果? - Florian Albrecht
我希望在绘制完成后(所有的绘制)调用该函数。我试图修改已经绘制的某些元素(在它们绘制之后)。但是我的函数甚至在绘制完成前就被调用了。 - Dinesh
所以你是在解决与这个问题不同的另一个问题,对吗?如果是这样,也许创建另一个问题会是正确的方法... - Florian Albrecht

2

使用以下逻辑在nvd3中有选择地使某些系列的点启用。

//i is the series number; starts with 0

var selector = 'g.nv-series-'+i+' circle';
d3.selectAll(selector).classed("hover",true);

然而,在数据中添加一个额外的参数(例如 'enable_points':'true') 会更有意义。我希望能够推动这个想法并对nvd3进行一些更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接