Multipage SVG with R
When using layout
in lattice::xyplot
with trellis.device
you can get several pages in a PDF:
trellis.device(pdf, file="myfile.pdf")
data(mtcars)
xyplot(hp~mpg|gear, data=mtcars, l开发者_Python百科ayout=c(1, 1))
dev.off()
I would like to use the same approach to get a multi-page SVG. I have tried cairo::svg
, and the packages gridSVG
, SVGAnnotation
and RSVGTipsDevice
with no success: only the last page of the trellis
object is saved.
Is there any solution using R code?
Thanks!
I finally decided to ask directy to Paul Murrell, the creator of grid and gridSVG. He kindly provided some good advices and code which completely solved the problem with an approach similar to the advice from @mbq. I modified his code to write this function:
library(gridSVG)
library(XML)
animateTrellis <- function(object, file='animatedSVG.svg',
duration=.1, step=2, show=TRUE){
nLayers <- dim(object)
stopifnot(nLayers>1)
for (i in seq_len(nLayers)){
p <- object[i]
label <- p$condlevels[[1]][i]
##Create intermediate SVG files
g <- grid.grabExpr(print(p, prefix=label),
name=label)
if (i==1){ ## First frame
ga <- animateGrob(g, group=TRUE,
visibility="hidden",
duration=duration, begin=step)
} else if (i==nLayers){ ##Last Frame
gg <- garnishGrob(g, visibility='hidden')
ga <- animateGrob(gg, group=TRUE,
visibility="visible",
duration=duration, begin=step*(i-1))
} else { ##any frame
gg <- garnishGrob(g, visibility='hidden')
gaV <- animateGrob(gg, group=TRUE,
visibility="visible",
duration=duration, begin=step*(i-1))
ga <- animateGrob(gaV, group=TRUE,
visibility="hidden",
duration=duration, begin=step*i)
}
grid.newpage()
grid.draw(ga)
fich <- tempfile(fileext='.svg')
gridToSVG(fich)
## Combine all
if (i==1) {
svgTop <- xmlParse(fich)
nodeTop <- getNodeSet(svgTop,
"//svg:g[@id='gridSVG']",
c(svg="http://www.w3.org/2000/svg"))[[1]]
} else {
svgChildren <- xmlParse(fich)
node <- getNodeSet(svgChildren,
"//svg:g[@id='gridSVG']/*",
c(svg="http://www.w3.org/2000/svg"))
addChildren(nodeTop, node)
}
unlink(fich)
}
saveXML(svgTop, file=file)
dev.off()
if (show) browseURL(file)
invisible(svgTop)
}
Then I can produce the SVG file with animation:
p <- xyplot(Sepal.Length~Petal.Length|Species, data=iris, layout=c(1, 1))
animateTrellis(p, file='iris.svg')
精彩评论