Is an NVD3 Line Plot with Markers Possible?
Asked Answered
D

5

20

I'm making an NVD3 line plot that will have significantly improved clarity if I can get markers to show for each data point instead of just the line itself. Unfortunately, I haven't been able to find an easy way to do this with NVD3 yet. I also considered using a scatter plot, but I couldn't figure out how to show connecting lines between the points. A third option I considered was to overlay a line and scatter plot, but this would show each series twice in the legend and may cause other unnecessary visual complications.

Is there a way to elegantly pull this off yet? Sample code of my formatting technique is listed below, but the 'size' and 'shape' attributes in test_data have no effect on the line plot with the current code.

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;
});
Dissert answered 5/12, 2012 at 21:39 Comment(1)
Any solutions for nvd3 versions 1.8.6 or 1.8.4?Gristle
D
17

I also wanted to add markers in a project I was working on. Here is a solution my partner and I found.

First, you have to select all of the points in your chart and set the fill-opacity to 1:

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

Now your points will be visible. To adjust the size of each point you need to modify each one's "r" (for radius) attribute. This isn't a style so you can't do it with css. Here is some jQuery code that does the job. The 500 millisecond delay is so the code will not run before the chart is rendered. This snippet sets the radius to 3.5:

        setTimeout(function() {
            $('#my-chart .nv-lineChart circle.nv-point').attr("r", "3.5");
        }, 500);
Duax answered 24/1, 2013 at 0:39 Comment(4)
this is what I did as well, this is the solution.Plaid
However, this is to update or redraw the point, there would be an issue that the chart first draw the points with different radius on the screen, and then redraw another one with the r as 3.5 and a flash on the screen.Slopwork
I got see that in the source code, you can set a field of size for each data, however, I tried but it does not work and there is a line of code: Math.sqrt(z(getSize(d,i))/Math.PI) to compute the r attribute.Slopwork
This seems to work for version 1.8.1 but not the recent versions of 1.8.4 or 1.8.6. Any solutions for that?Gristle
S
11

This puzzled me until I got help from the community:

css styling of points in figure

So here is my solution, based on css:

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

If anyone has come here from rCharts, below is a rmarkdown template to create an nPlot with both lines and markers:

 ```{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)
```
Semi answered 11/1, 2015 at 23:53 Comment(0)
T
4

The current version of nvd3 use path instead of circle to draw markers. Here is a piece of css code that i used to show markers.

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

And I also write something about this in https://github.com/novus/nvd3/issues/321, you could find that how i change the shape of makers.

I don't know how to change the size of markers. Trying to find a solution.

Tva answered 19/10, 2013 at 5:16 Comment(1)
Thanks. I refer the code you mentioned, and it helped me to transform in one specific series to scatter chart. But I am not able to change shape. I am using it with angularjs and using angular-nvd3 directive - github.com/krispo/angular-nvd3/issues/44Iodous
M
2

Selectively enable points to some series using the following logic in nvd3.

//i is the series number; starts with 0

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

However an additional parameter( like say 'enable_points':'true') in the data would make better sense. I will hopefully push some changes to nvd3 with this idea.

Marketa answered 17/9, 2013 at 17:8 Comment(0)
G
2

For current version of NVD3 (1.8.x), I use this D3-based solution (scripting only, no CSS file or style block required):

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");
}
);

The styles used are exactly the styles added by NVD3 by applying the "hover" class to each point (when hovered). Adjust them to your needs.

Grane answered 20/4, 2016 at 13:25 Comment(4)
I implemented this solution above but i am not sure why my callback function is being called before the chart is drawn.Gristle
@Gristle The function is called after the chart is added to the document (as the inline comment says), not necessarily after it is drawn. What (unwanted) effect do you encounter?Grane
I want the function to be called after the plot is completely drawn (all plotted). I am trying to modify the certain elements which are plotted (after they are plot). But my function is being called even before the plot is complete.Gristle
So you are trying to solve another problem than the one this question is about, right? In this case, perhaps creating another question would be the right approach here...Grane

© 2022 - 2024 — McMap. All rights reserved.