I would like to create plots in standalone HTML file from Rmarkdown and I think SVG would be a great way to include the graphics.
However, even when setting dev='svg'
, the graphics aren't in text SVG.
MWE (with abbreviated javascript and img):
---
title: "SVG Plot"
output: html_document
---
```{r pressure, dev='svg'}
hist(1:4, xaxt='n', yaxt='n', ann=FALSE)
```
Yet this gives the following HTML code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
<title>SVG Plot</title>
<script src="data:application/x-javascript;base64,LyohIGpRdWVyeSB2MS4xMS4zIHwgKGM.......bmdPbkxvYWQoKTsKCg=="></script>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
pre:not([class]) {
background-color: white;
}
</style>
<script type="text/javascript">
if (window.hljs && document.readyState && document.readyState === "complete") {
window.setTimeout(function() {
hljs.initHighlighting();
}, 0);
}
</script>
<style type="text/css">
h1 {
font-size: 34px;
}
h1.title {
font-size: 38px;
}
h2 {
font-size: 30px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 16px;
}
h6 {
font-size: 12px;
}
.table th:not([align]) {
text-align: left;
}
</style>
</head>
<body>
<style type="text/css">
.main-container {
max-width: 940px;
margin-left: auto;
margin-right: auto;
}
code {
color: inherit;
background-color: rgba(0, 0, 0, 0.04);
}
img {
max-width:100%;
height: auto;
}
.tabbed-pane {
padding-top: 12px;
}
button.code-folding-btn:focus {
outline: none;
}
</style>
<div class="container-fluid main-container">
<!-- tabsets -->
<script>
$(document).ready(function () {
window.buildTabsets("TOC");
});
</script>
<!-- code folding -->
<div class="fluid-row" id="header">
<h1 class="title toc-ignore">SVG Plot</h1>
</div>
<pre class="r"><code>hist(1:4, xaxt='n', yaxt='n', ann=FALSE)</code></pre>
<p><img src="data:image/svg+xml;base64,PD94bWwgdmV...............KPC9nPgo8L3N2Zz4K" width="672" /></p>
</div>
<script>
// add bootstrap table styles to pandoc tables
function bootstrapStylePandocTables() {
$('tr.header').parent('thead').parent('table').addClass('table table-condensed');
}
$(document).ready(function () {
bootstrapStylePandocTables();
});
</script>
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
document.getElementsByTagName("head")[0].appendChild(script);
})();
</script>
</body>
</html>
Is there any way to just get text SVG graphics (e.g. what svg()
or ggsave()
outputs)?
EDIT: svg()
example:
svg('base.svg')
hist(1:4, xaxt='n', yaxt='n', ann=FALSE)
dev.off()
Gives:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="504pt" height="504pt" viewBox="0 0 504 504" version="1.1">
<defs>
<clipPath id="clip1">
<path d="M 59.039063 59.039063 L 474.757813 59.039063 L 474.757813 431.558594 L 59.039063 431.558594 Z M 59.039063 59.039063 "/>
</clipPath>
</defs>
<g id="surface6">
<rect x="0" y="0" width="504" height="504" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
<g clip-path="url(#clip1)" clip-rule="nonzero">
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 74.398438 416.800781 L 202.398438 416.800781 L 202.398438 72.800781 L 74.398438 72.800781 Z M 74.398438 416.800781 "/>
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 202.398438 416.800781 L 330.398438 416.800781 L 330.398438 244.800781 L 202.398438 244.800781 Z M 202.398438 416.800781 "/>
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 330.398438 416.800781 L 458.398438 416.800781 L 458.398438 244.800781 L 330.398438 244.800781 Z M 330.398438 416.800781 "/>
</g>
</g>
</svg>
Also, if there is a way to get text SVG, is there a good reason why this isn't preferred?
A text SVG can be achieved (though using the svglite package, which is less accurate than base svg()
):
---
title: "SVG Plot"
output: html_document
---
```{r setup, include=FALSE}
library(knitr)
local({
hook_plot = knit_hooks$get('plot')
knit_hooks$set(plot = function(x, options) {
x = paste(x, collapse = '.')
if (!grepl('\\.svg', x)) return(hook_plot(x, options))
# read the content of the svg image and write it out without <?xml ... ?>
paste(readLines(x)[-1], collapse = '\n')
})
})
```
```{r pressure, dev='svg'}
hist(1:4, xaxt='n', yaxt='n', ann=FALSE)
```
This gives:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
<title>SVG Plot</title>
<script src="data:application/x-javascript;base64,LyohIGpRdWVyeSB2MS4xM.........ihiKX0odGhpcyxkb2N1bWVudCk7Cn07Cg=="></script>
<script src="data:application/x-javascript;base64,LyohIFJlc3BvbmQuanMg........SgpOwpobGpzLmluaXRIaWdobGlnaHRpbmdPbkxvYWQoKTsKCg=="></script>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
pre:not([class]) {
background-color: white;
}
</style>
<script type="text/javascript">
if (window.hljs && document.readyState && document.readyState === "complete") {
window.setTimeout(function() {
hljs.initHighlighting();
}, 0);
}
</script>
<style type="text/css">
h1 {
font-size: 34px;
}
h1.title {
font-size: 38px;
}
h2 {
font-size: 30px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 16px;
}
h6 {
font-size: 12px;
}
.table th:not([align]) {
text-align: left;
}
</style>
</head>
<body>
<style type="text/css">
.main-container {
max-width: 940px;
margin-left: auto;
margin-right: auto;
}
code {
color: inherit;
background-color: rgba(0, 0, 0, 0.04);
}
img {
max-width:100%;
height: auto;
}
.tabbed-pane {
padding-top: 12px;
}
button.code-folding-btn:focus {
outline: none;
}
</style>
<div class="container-fluid main-container">
<!-- tabsets -->
<script>
$(document).ready(function () {
window.buildTabsets("TOC");
});
</script>
<!-- code folding -->
<div class="fluid-row" id="header">
<h1 class="title toc-ignore">SVG Plot</h1>
</div>
<pre class="r"><code>hist(1:4, xaxt='n', yaxt='n', ann=FALSE)</code></pre>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="504pt" height="360pt" viewBox="0 0 504 360" version="1.1">
<defs> <clipPath id="clip1"> <path d="M 59.039063 59.039063 L 474.757813 59.039063 L 474.757813 287.558594 L 59.039063 287.558594 Z M 59.039063 59.039063 "></path> </clipPath> </defs> <g id="surface1"> <rect x="0" y="0" width="504" height="360" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"></rect> <g clip-path="url(#clip1)" clip-rule="nonzero"> <path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 74.398438 278.132813 L 202.398438 278.132813 L 202.398438 67.464844 L 74.398438 67.464844 Z M 74.398438 278.132813 "></path> <path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 202.398438 278.132813 L 330.398438 278.132813 L 330.398438 172.800781 L 202.398438 172.800781 Z M 202.398438 278.132813 "></path> <path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 330.398438 278.132813 L 458.398438 278.132813 L 458.398438 172.800781 L 330.398438 172.800781 Z M 330.398438 278.132813 "></path> </g> </g>
</svg>
</div>
<script>
// add bootstrap table styles to pandoc tables
function bootstrapStylePandocTables() {
$('tr.header').parent('thead').parent('table').addClass('table table-condensed');
}
$(document).ready(function () {
bootstrapStylePandocTables();
});
</script>
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
(function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
document.getElementsByTagName("head")[0].appendChild(script);
})();
</script>
</body>
</html>
This is based on the comment by @yihui on the issue posted by @cboettig here (you can now use the CRAN version of knitr).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With