diff --git a/DESCRIPTION b/DESCRIPTION index 00ac0ea..4bfcf5f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: sunburstR Type: Package Title: htmlwidget for Kerry Rodden d3.js sequence sunburst -Version: 0.2.3 -Date: 2016-03-08 +Version: 0.2.4 +Date: 2016-05-18 Authors@R: c( person( "Mike", "Bostock" @@ -19,6 +19,11 @@ Authors@R: c( , role = c("aut", "cre") , comment = "R interface" , email = "kent.russell@timelyportfolio.com" + ), + person( + "Florian", "Breitwieser" + , role = c("ctb") + , comment = "R interface" ) ) Maintainer: Kent Russell diff --git a/R/sunburst.R b/R/sunburst.R index 5bae049..68b9790 100644 --- a/R/sunburst.R +++ b/R/sunburst.R @@ -17,7 +17,7 @@ #' @param breadcrumb,legend \code{list} to customize the breadcrumb trail or legend. This argument #' should be in the form \code{list(w =, h =, s =, t = )} where #' \code{w} is the width, \code{h} is the height, \code{s} is the spacing, -#' and \code{t} is the tail all in \code{px}. Set \code{w} to \code{0} for +#' and \code{t} is the tail all in \code{px}. \code{w} is \code{0} by default for #' breadcrumbs widths based on text length. #' @param sortFunction \code{\link[htmlwidgets]{JS}} function to sort the slices. #' The default sort is by size. diff --git a/inst/examples/example_replicate.R b/inst/examples/example_replicate.R index c1636f8..3b390be 100644 --- a/inst/examples/example_replicate.R +++ b/inst/examples/example_replicate.R @@ -35,12 +35,14 @@ sunburst(jsondata = sequence_json) # try with csv data from this fork # https://gist.github.com/mkajava/7515402 -# works technically but not cosmetically -sunburst( csvdata = read.csv( - file = "https://gist.githubusercontent.com/mkajava/7515402/raw/9f80d28094dc9dfed7090f8fb3376ef1539f4fd2/comment-sequences.csv" - ,header = FALSE - ,stringsAsFactors = FALSE -)) +# great use for new breadbrumb wrapping +sunburst( + csvdata = read.csv( + file = "https://gist.githubusercontent.com/mkajava/7515402/raw/9f80d28094dc9dfed7090f8fb3376ef1539f4fd2/comment-sequences.csv" + ,header = FALSE + ,stringsAsFactors = FALSE + ) +) # try with csv data from this fork diff --git a/inst/htmlwidgets/lib/sequences/sequences.css b/inst/htmlwidgets/lib/sequences/sequences.css index ac1f130..b687031 100644 --- a/inst/htmlwidgets/lib/sequences/sequences.css +++ b/inst/htmlwidgets/lib/sequences/sequences.css @@ -11,10 +11,10 @@ .sunburst-sequence { width: 100%; - height: 70px; position: absolute; top: 0px; left: 0px; + pointer-events: none; } .sunburst-legend { diff --git a/inst/htmlwidgets/sunburst.js b/inst/htmlwidgets/sunburst.js index 8ae1e17..942c113 100644 --- a/inst/htmlwidgets/sunburst.js +++ b/inst/htmlwidgets/sunburst.js @@ -15,7 +15,7 @@ HTMLWidgets.widget({ // remove previous in case of Shiny/dynamic d3.select(el).select(".sunburst-chart svg").remove(); - // Dimensions of sunburst. + // Dimensions of sunburst var width = el.getBoundingClientRect().width - (x.options.legend.w ? x.options.legend.w : 75); var height = el.getBoundingClientRect().height - 70; var radius = Math.min(width, height) / 2; @@ -24,15 +24,10 @@ HTMLWidgets.widget({ .attr("width", width) .attr("height", height); - // function string_length for breadcrumbs - function string_length(s) { - return(s.length*7.5+12) - } - // Breadcrumb dimensions: width, height, spacing, width of tip/tail. // these will be the defaults var b = { - w: 75, h: 30, s: 3, t: 10 + w: 0, h: 30, s: 3, t: 10 }; // if breadcrumb is provided in the option, we will overwrite // with what is provided @@ -249,7 +244,7 @@ HTMLWidgets.widget({ // Add the svg area. var trail = d3.select(el).select(".sunburst-sequence").append("svg") .attr("width", width) - .attr("height", 50) + //.attr("height", 50) .attr("id", el.id + "-trail"); // Add the label at the end, for the percentage. trail.append("text") @@ -296,24 +291,9 @@ HTMLWidgets.widget({ // Calculate positions of breadcrumbs based on string lengths var curr_breadcrumb_x = 0; nodeArray[0].breadcrumb_x = 0; - nodeArray[0].string_length = string_length(nodeArray[0].name); nodeArray[0].breadcrumb_h = 0; - for (var k=1; k width*0.99) { - nodeArray[k].breadcrumb_h += b.h; // got to next line - curr_breadcrumb_x = b.t + b.s; // restart counter - } - nodeArray[k].breadcrumb_x = curr_breadcrumb_x; - nodeArray[k].string_length = my_string_length; - } - entering.append("polygon") - .attr("points", breadcrumbPoints) .style("z-index",function(d,i) { return(999-i); }) .style("fill", function(d) { return colors(d.name); }); @@ -324,21 +304,59 @@ HTMLWidgets.widget({ .attr("text-anchor", "left") .text(function(d) { return d.name; }); + // Remove exiting nodes. + g.exit().remove(); + + // loop through each g element + // calculate string length + // draw the breadcrumb polygon + // and determine if breadcrumb should be wrapped to next row + g.each(function(d,k){ + var crumbg = d3.select(this); + var my_string_length = crumbg.select("text").node().getBoundingClientRect().width; + nodeArray[k].string_length = my_string_length + 12; + crumbg.select("polygon").attr("points", function(d){ + return breadcrumbPoints(d, k); + }); + var my_g_length = crumbg.node().getBoundingClientRect().width; + curr_breadcrumb_x += k===0 ? 0 : nodeArray[k-1].string_length + b.s; + nodeArray[k].breadcrumb_h = k===0 ? 0 : nodeArray[k-1].breadcrumb_h; + + if (curr_breadcrumb_x + my_g_length > width*0.99) { + nodeArray[k].breadcrumb_h += b.h; // got to next line + curr_breadcrumb_x = b.t + b.s; // restart counter + } + nodeArray[k].breadcrumb_x = curr_breadcrumb_x; + }); + + // Set position for entering and updating nodes. g.attr("transform", function(d, i) { return "translate(" + d.breadcrumb_x + ", "+d.breadcrumb_h+")"; }); - // Remove exiting nodes. - g.exit().remove(); // Now move and update the percentage at the end. d3.select(el).select("#" + el.id + "-trail").select("#" + el.id + "-endlabel") - .attr("x", (nodeArray[nodeArray.length-1].breadcrumb_x + nodeArray[nodeArray.length-1].string_length + b.s + 30 )) - .attr("y", nodeArray[nodeArray.length-1].breadcrumb_h + b.h / 2) + .attr("x", function(d){ + var bend = d3.select(this); + var curr_breadcrumb_x = nodeArray[nodeArray.length-1].breadcrumb_x + nodeArray[nodeArray.length-1].string_length + b.t + b.s; + var my_g_length = bend.node().getBoundingClientRect().width; + + var curr_breadcrumb_h = nodeArray[nodeArray.length-1].breadcrumb_h + b.h/2; + if (curr_breadcrumb_x + my_g_length > width*0.99) { + curr_breadcrumb_h += b.h + b.h/2; + curr_breadcrumb_x = b.t + b.s; // restart counter + } + bend.datum({ + "breadcrumb_x": curr_breadcrumb_x, + "breadcrumb_h": curr_breadcrumb_h + }); + return curr_breadcrumb_x; + }) + .attr("y", function(d){return d.breadcrumb_h}) .attr("dy", "0.35em") - .style("font-size","small") - .attr("text-anchor", "middle") + .attr("text-anchor", "start") .text(percentageString); diff --git a/man/sunburst.Rd b/man/sunburst.Rd index 05acf6d..7863b7f 100644 --- a/man/sunburst.Rd +++ b/man/sunburst.Rd @@ -31,7 +31,7 @@ of the sunburst. Note, this will override \code{percent} and \code{count}.} \item{breadcrumb, legend}{\code{list} to customize the breadcrumb trail or legend. This argument should be in the form \code{list(w =, h =, s =, t = )} where \code{w} is the width, \code{h} is the height, \code{s} is the spacing, -and \code{t} is the tail all in \code{px}. Set \code{w} to \code{0} for +and \code{t} is the tail all in \code{px}. \code{w} is \code{0} by default for breadcrumbs widths based on text length.} \item{sortFunction}{\code{\link[htmlwidgets]{JS}} function to sort the slices. @@ -60,8 +60,6 @@ sunburst(sequences) sunburst( sequences ,count = TRUE - , breadcrumb=list(w=0, h=10,s=2,t=2) - , legend=list(w=200, h=20, s=3, r=3) ) sunburst( @@ -81,12 +79,14 @@ sunburst(jsondata = sequence_json) # try with csv data from this fork # https://gist.github.com/mkajava/7515402 -# works technically but not cosmetically -sunburst( csvdata = read.csv( - file = "https://gist.githubusercontent.com/mkajava/7515402/raw/9f80d28094dc9dfed7090f8fb3376ef1539f4fd2/comment-sequences.csv" - ,header = FALSE - ,stringsAsFactors = FALSE -)) +# great use for new breadbrumb wrapping +sunburst( + csvdata = read.csv( + file = "https://gist.githubusercontent.com/mkajava/7515402/raw/9f80d28094dc9dfed7090f8fb3376ef1539f4fd2/comment-sequences.csv" + ,header = FALSE + ,stringsAsFactors = FALSE + ) +) # try with csv data from this fork @@ -150,6 +150,5 @@ ngrams2 \%>>\% ) \%>>\% tagList \%>>\% browsable - }