I have a shiny application that uses the nvd3 library from rCharts. I have provided a fully reproducible example below:
library(shiny)
library(reshape2)
library(ggplot2)
testing <- function() {
shinyApp(
options = list(launch.browser = TRUE),
ui = fluidPage(
titlePanel("test"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
rCharts::showOutput("plot1", "nvd3"),
rCharts::showOutput("plot2", "nvd3")
)
)
),
server = function(input, output) {
output$plot1 <- rCharts::renderChart2({
ecm <- reshape2::melt(economics[,c('date', 'uempmed', 'psavert')], id = 'date')
g <- nPlot(value ~ date, group = 'variable', data = ecm, type = 'lineWithFocusChart')
#let's add this to make date handling easier
g$xAxis( tickFormat="#!function(d) {return d3.time.format('%b %Y')(new Date( d * 86400000 ));}!#" )
#grab template from
#https://github.com/ramnathv/rCharts/blob/master/inst/libraries/nvd3/layouts/chart.html
#modify to add callback on graph render
after_script <-
"
function drawVerticalLines( opts ){
if (!(d3.select('#' + opts.id + ' .nvd3 .nv-focus .nv-linesWrap').select('.vertical-lines')[0][0])) {
d3.select('#' + opts.id + ' .nvd3 .nv-focus .nv-linesWrap').append('g')
.attr('class', 'vertical-lines')
d3.select('#' + opts.id).insert('h3','svg')
.text('Test');
}
vertLines = d3.select('#' + opts.id + ' .nvd3 .nv-focus .nv-linesWrap').select('.vertical-lines').selectAll('.vertical-line')
.data(
[
_
] )
var vertG = vertLines.enter()
.append('g')
.attr('class', 'vertical-line')
vertG.append('svg:line')
vertG.append('text')
vertLines.exit().remove()
vertLines.selectAll('line')
.attr('x1', function(d){
return chart.xAxis.scale()(d.date/60/60/24/1000)
})
.attr('x2', function(d){ return chart.xAxis.scale()(d.date/60/60/24/1000) })
.attr('y1', chart.yAxis.scale().range()[0] )
.attr('y2', chart.yAxis.scale().range()[1] )
.style('stroke', 'red')
vertLines.selectAll('text')
.text( function(d) { return d.label })
.attr('dy', '1em')
//x placement ; change dy above for minor adjustments but mainly
// change the d.date/60/60/24/1000
//y placement ; change 2 to where you want vertical placement
//rotate -90 but feel free to change to what you would like
.attr('transform', function(d){
return 'translate(' +
chart.xAxis.scale()(d.date/60/60/24/1000) +
',' +
chart.yAxis.scale()(2) +
') rotate(-90)'
})
//also you can style however you would like
//here is an example changing the font size
.style('font-size','80%')
}
"
temp <- "{ 'date' : new Date('1997-12-25'), 'label' : '83613223.8687485' },{ 'date' : new Date('1975-12-26'), 'label' : '83866338.1127959' },{ 'date' : new Date('1960-12-29'), 'label' : '85663720.9007578' },{ 'date' : new Date('1964-12-30'), 'label' : '84730972.6070318' },{ 'date' : new Date('1963-12-31'), 'label' : '82158524.7138574' }"
replacement <- sub("_", temp, after_script)
g$setTemplate(script = sprintf("
<script type='text/javascript'>
$(document).ready(function(){
draw{{chartId}}( );
});
function draw{{chartId}}( ){
var opts = {{{ opts }}};
var 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() {
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);
chart.dispatch.brush.on('brushstart',function(){ drawVerticalLines( opts ) });
chart.dispatch.brush.on(
'brushend',
function(){ window.setTimeout(
function() {drawVerticalLines( opts )},
250
)}
);
nv.utils.windowResize(chart.update);
return chart;
},%s);
};
%s
</script>
"
,
#here is where you can type your vertical line/label function
"function() { drawVerticalLines( opts ) }"
,
#add the afterScript here if using with shiny
replacement
))
g
})
output$plot2 <- rCharts::renderChart2({
ecm <- reshape2::melt(economics[,c('date', 'uempmed', 'psavert')], id = 'date')
g <- nPlot(value ~ date, group = 'variable', data = ecm, type = 'lineWithFocusChart')
#let's add this to make date handling easier
g$xAxis( tickFormat="#!function(d) {return d3.time.format('%b %Y')(new Date( d * 86400000 ));}!#" )
#grab template from
#https://github.com/ramnathv/rCharts/blob/master/inst/libraries/nvd3/layouts/chart.html
#modify to add callback on graph render
after_script <-
"
function drawVerticalLines( opts ){
if (!(d3.select('#' + opts.id + ' .nvd3 .nv-focus .nv-linesWrap').select('.vertical-lines')[0][0])) {
d3.select('#' + opts.id + ' .nvd3 .nv-focus .nv-linesWrap').append('g')
.attr('class', 'vertical-lines')
d3.select('#' + opts.id).insert('h3','svg')
.text('Test');
}
vertLines = d3.select('#' + opts.id + ' .nvd3 .nv-focus .nv-linesWrap').select('.vertical-lines').selectAll('.vertical-line')
.data(
[
_
] )
var vertG = vertLines.enter()
.append('g')
.attr('class', 'vertical-line')
vertG.append('svg:line')
vertG.append('text')
vertLines.exit().remove()
vertLines.selectAll('line')
.attr('x1', function(d){
return chart.xAxis.scale()(d.date/60/60/24/1000)
})
.attr('x2', function(d){ return chart.xAxis.scale()(d.date/60/60/24/1000) })
.attr('y1', chart.yAxis.scale().range()[0] )
.attr('y2', chart.yAxis.scale().range()[1] )
.style('stroke', 'red')
vertLines.selectAll('text')
.text( function(d) { return d.label })
.attr('dy', '1em')
//x placement ; change dy above for minor adjustments but mainly
// change the d.date/60/60/24/1000
//y placement ; change 2 to where you want vertical placement
//rotate -90 but feel free to change to what you would like
.attr('transform', function(d){
return 'translate(' +
chart.xAxis.scale()(d.date/60/60/24/1000) +
',' +
chart.yAxis.scale()(2) +
') rotate(-90)'
})
//also you can style however you would like
//here is an example changing the font size
.style('font-size','80%')
}
"
temp <- "{ 'date' : new Date('1997-12-25'), 'label' : '83613223.8687485' },{ 'date' : new Date('1975-12-26'), 'label' : '83866338.1127959' },{ 'date' : new Date('1960-12-29'), 'label' : '85663720.9007578' },{ 'date' : new Date('1964-12-30'), 'label' : '84730972.6070318' },{ 'date' : new Date('1963-12-31'), 'label' : '82158524.7138574' }"
replacement <- sub("Test", "Not a Test", sub("_", temp, after_script))
g$setTemplate(script = sprintf("
<script type='text/javascript'>
$(document).ready(function(){
draw{{chartId}}( );
});
function draw{{chartId}}( ){
var opts = {{{ opts }}};
var 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() {
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);
chart.dispatch.brush.on('brushstart',function(){ drawVerticalLines( opts ) });
chart.dispatch.brush.on(
'brushend',
function(){ window.setTimeout(
function() {drawVerticalLines( opts )},
250
)}
);
nv.utils.windowResize(chart.update);
return chart;
},%s);
};
%s
</script>
"
,
#here is where you can type your vertical line/label function
"function() { drawVerticalLines( opts ) }"
,
#add the afterScript here if using with shiny
replacement
))
g
})
})
}
testing()
This is almost the same as the example made by timelyportfolio here: http://rcharts.io/viewer/?80d85f78a5a975fa29d7#.VcidCp1Viko
However, I have added some more javascript at the
d3.select('#' + opts.id).insert('h3','svg')
.text('Test');
section, which allows me to create a title as well. However, my first plot uses the title "Test", whereas the second plot uses the title "Not a Test", but when I plot both, only the title "Not a Test" shows up, and it shows up as the title for both plots surprisingly. Furthermore, I also saw that both plots take everything from one template (not just the title), so if I added different data (different dates and labels in this case) for different plots, only the dates and labels specified in one of the plots would show up, and it would show up as the data for the other plot as well. This is exceedingly strange, because I also printed out the exact javascript text I was using as the afterscript, and they are different across the two plots, but this is not the case when I actually render the plots in my shiny application. Does anyone have any idea why this is happening? If more details are needed, I would be happy to provide them! Thank you!