Wednesday, October 8, 2014

Responsive SVG in Your RStudio Browser

For those readers who are unaware, SVG is absolutely amazing, and if you need some convincing see this 2009 paper/talk from David Dailey Why is SVG Going to Be REALLY BIG?  Most R users should be very well acquainted with graphics and plots magically appearing on the screen with certain commands.  These graphics though are rasters, so when you resize, the graphics are re-rendered to scale.  Let’s have a look with a simple plot.

plot(x=1:10,y=1:10,type="b")



R_raster_resize


One of the beauties of SVG is that it will scale without re-rendering.  The old way to create SVG in R was to do something like this which produces an svg file that we can use, adjust, and share.

svg("svgplot.svg")
plot(x=1:10,y=1:10,type="b")
dev.off()

However, the integrated browser window in RStudio combined with the HTML helper tools  from RStudio lets us produce and see SVGs in real-time.  Let’s look again at our simple plot, but this time as an SVG in our RStudio browser window.  We will also use the precocious packages SVGAnnotation and XML from Duncan Temple Lang.


R_svg_1


 


But where is the magic resizability ?


 


This is where we will use some help from



Sara Soueidan - Understanding SVG Coordinate Systems & Transformations (Part 1) – The viewport, viewBox, & preserveAspectRatio



Dudley Storey - Make SVG Responsive


We can make a simple function to help us change the attributes and style to get a fancy responsive SVG real-time.

#even better make it responsive
#use this post as a guide
#http://demosthenes.info/blog/744/Make-SVG-Responsive
respXML <- function( svg_xml, height = NULL, width = "100%", print = T, ... ){
# svg_xml should be an XML document
library(htmltools)
library(pipeR)
library(XML)

tags$div(
style = paste(
sprintf('width:%s;',width)
,ifelse(!is.null(height),sprintf('height:%s;',height),"")
,"display: inline-block;"
,"position: relative;"
,"padding-bottom: 100%;"
,"vertical-align: middle;"
,"overflow: hidden;"
)
, ...
,svg_xml %>>%
(~svg ~
structure(ifelse(
length(getDefaultNamespace(svg)) > 0
,getNodeSet(svg,"//x:svg", "x")
,getNodeSet(svg,"//svg")
),class="XMLNodeSet") %>>%
xmlApply(
function(s){
a = xmlAttrs(s)
removeAttributes(s)
xmlAttrs(s) <- a[-(1:2)]
xmlAttrs(s) <- c(
style = paste0(
#"height:100%;width:100%;"
"display: inline-block;"
#post says use these but will not fit viewer
#,"position: absolute;"
#,"top: 0;"
#,"left: 0;"
)
#,preserveAspectRatio="xMidYMid meet"
)
}
)
) %>>%
saveXML %>>%
HTML
) %>>%
( ~ if(print) html_print(.) ) %>>%
( return( invisible( . ) ) )

Let’s test our fancy new function.





R_svg_2


 


That’s more like it.  Let’s abandon the animated GIFs and embed a SVG below (copied/pasted straight from R into this post).  Resize your browser and test the result.


Actually, it appears I lied. The SVG does not resize like it would outside the Blogger container.  See http://bl.ocks.org/timelyportfolio/raw/560e50e437d4bb1b9142/ for the SVG in a standalone document for resizing.

# example using dotchart documentation
# in R graphics package
# ?graphics::dotchart
svgPlot(
dotchart(
t(VADeaths)
, xlim = c(0,100)
, main = "Death Rates in Virginia - 1940"
)
) %>>%
respXML



No comments:

Post a Comment