block by timelyportfolio 90bd56b7f46d45f02172

nvd3 ugly labels instead of tooltips

Full Screen

In response to Stack Overflow Fix label with rCharts in a shiny application, we can slightly modify the standard script template from rCharts to perform the labelling as a callback function to nv.addGraph.

I don’t think I have seen this even in the nvd3 examples.

rCharts Viewer demo

rCharts live example

index.html

<!doctype HTML>
<meta charset = 'utf-8'>
<html>
  <head>
    <link rel='stylesheet' href='//nvd3.org/assets/css/nv.d3.css'>
    
    <script src='//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js' type='text/javascript'></script>
    <script src='//d3js.org/d3.v3.min.js' type='text/javascript'></script>
    <script src='//timelyportfolio.github.io/rCharts_nvd3_tests/libraries/widgets/nvd3/js/nv.d3.min-new.js' type='text/javascript'></script>
    <script src='//nvd3.org/assets/lib/fisheye.js' type='text/javascript'></script>
    
    <style>
    .rChart {
      display: block;
      margin-left: auto; 
      margin-right: auto;
      width: 800px;
      height: 400px;
    }  
    </style>
    
  </head>
  <body >
    
    <div id = 'chart6483d53bb6' class = 'rChart nvd3'></div>    
    
  <script type='text/javascript'>
    $(document).ready(function(){
      drawchart6483d53bb6()
    });
  function drawchart6483d53bb6(){  
    var opts = {
 "dom": "chart6483d53bb6",
"width":    800,
"height":    400,
"x": "tall",
"y": "age",
"type": "scatterChart",
"id": "chart6483d53bb6" 
},
    data = [
 {
 "age": 1,
"tall":            0.5,
"name": "a1" 
},
{
 "age": 2,
"tall": 0.5736842105263,
"name": "b2" 
},
{
 "age": 3,
"tall": 0.6473684210526,
"name": "c3" 
},
{
 "age": 4,
"tall": 0.7210526315789,
"name": "d4" 
},
{
 "age": 5,
"tall": 0.7947368421053,
"name": "e5" 
},
{
 "age": 6,
"tall": 0.8684210526316,
"name": "f6" 
},
{
 "age": 7,
"tall": 0.9421052631579,
"name": "g7" 
},
{
 "age": 8,
"tall": 1.015789473684,
"name": "h8" 
},
{
 "age": 9,
"tall": 1.089473684211,
"name": "i9" 
},
{
 "age": 10,
"tall": 1.163157894737,
"name": "j10" 
},
{
 "age": 11,
"tall": 1.236842105263,
"name": "k11" 
},
{
 "age": 12,
"tall": 1.310526315789,
"name": "l12" 
},
{
 "age": 13,
"tall": 1.384210526316,
"name": "m13" 
},
{
 "age": 14,
"tall": 1.457894736842,
"name": "n14" 
},
{
 "age": 15,
"tall": 1.531578947368,
"name": "o15" 
},
{
 "age": 16,
"tall": 1.605263157895,
"name": "p16" 
},
{
 "age": 17,
"tall": 1.678947368421,
"name": "q17" 
},
{
 "age": 18,
"tall": 1.752631578947,
"name": "r18" 
},
{
 "age": 19,
"tall": 1.826315789474,
"name": "s19" 
},
{
 "age": 20,
"tall":            1.9,
"name": "t20" 
} 
]
    
    if(!(opts.type==='pieChart' || opts.type==='sparklinePlus' || opts.type==='bulletChart')) {
      var data = d3.nest()
      .key(function(d){
        //return opts.group === undefined ? 'main' : d[opts.group]
        //instead of main would think a better default is opts.x
        return opts.group === undefined ? opts.y : d[opts.group];
      })
      .entries(data);
    }
    
    if (opts.disabled != undefined){
      data.map(function(d, i){
        d.disabled = opts.disabled[i]
      })
    }
    
    nv.addGraph(function() {
      var chart = nv.models[opts.type]()
      .width(opts.width)
      .height(opts.height)
      
      if (opts.type != 'bulletChart'){
        chart
        .x(function(d) { return d[opts.x] })
        .y(function(d) { return d[opts.y] })
      }
      
      


chart.xAxis
  .axisLabel("the age")



chart.yAxis
  .axisLabel("the tall")
  .width(    50)

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

nv.utils.windowResize(chart.update);
return chart;
    },
function(){
  //for each circle or point that we have
  // add a text label with information
  d3.selectAll('.nv-group circle').each(function( ){
        d3.select(d3.select(this).node().parentNode).append('text')
          .datum( d3.select(this).data() )
          .text( function(d) {
            //you'll have access to data here so you can
            //pick and choose
            //as example just join all the info into one line
            return Object.keys(d[0]).map(function( key ){
              return( key + ':' +  d[0][key] )
            }).join()
          })
          .attr('x',d3.select(this).attr('cx'))
          .attr('y',d3.select(this).attr('cy'))
          .style('pointer-events','none')
      })
}
);
  };
</script>
    
    <script></script>    
  </body>
</html>

code.R

library(rCharts)
age <- c(1:20)
tall <- seq(0.5, 1.90, length = 20)
name <- paste(letters[1:20], 1:20, sep = "")
df <- data.frame(age = age, tall = tall, name = name)
n1 <- nPlot(age ~ tall ,data = df, type = "scatterChart", height = 400, width = 600)
n1$xAxis(axisLabel = "the age")
n1$yAxis(axisLabel = "the tall", width = 50)
#assuming you don't want tooltips if you have labels
#change back to what you had if assumption incorrect
n1$chart(tooltipContent = NULL)

#grab template from
#https://github.com/ramnathv/rCharts/blob/master/inst/libraries/nvd3/layouts/chart.html
#modify to add callback on graph render
n1$setTemplate(script = sprintf("
  <script type='text/javascript'>
    $(document).ready(function(){
      draw{{chartId}}()
    });
  function draw{{chartId}}(){  
    var opts = {{{ opts }}},
    data = {{{ data }}}
    
    if(!(opts.type==='pieChart' || opts.type==='sparklinePlus' || opts.type==='bulletChart')) {
      var data = d3.nest()
      .key(function(d){
        //return opts.group === undefined ? 'main' : d[opts.group]
        //instead of main would think a better default is opts.x
        return opts.group === undefined ? opts.y : d[opts.group];
      })
      .entries(data);
    }
    
    if (opts.disabled != undefined){
      data.map(function(d, i){
        d.disabled = opts.disabled[i]
      })
    }
    
    nv.addGraph(function() {
      var chart = nv.models[opts.type]()
      .width(opts.width)
      .height(opts.height)
      
      if (opts.type != 'bulletChart'){
        chart
        .x(function(d) { return d[opts.x] })
        .y(function(d) { return d[opts.y] })
      }
      
      
{{{ chart }}}

{{{ xAxis }}}

{{{ x2Axis }}}

{{{ yAxis }}}

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

nv.utils.windowResize(chart.update);
return chart;
    },%s);
  };
</script>
"
,
#here is where you can type your labelling function
"
function(){
  //for each circle or point that we have
  // add a text label with information
  d3.selectAll('.nv-group circle').each(function( ){
        d3.select(d3.select(this).node().parentNode).append('text')
          .datum( d3.select(this).data() )
          .text( function(d) {
            //you'll have access to data here so you can
            //pick and choose
            //as example just join all the info into one line
            return Object.keys(d[0]).map(function( key ){
              return( key + ':' +  d[0][key] )
            }).join()
          })
          .attr('x',d3.select(this).attr('cx'))
          .attr('y',d3.select(this).attr('cy'))
          .style('pointer-events','none')
      })
}
"
))

n1