What:在页面加载时,动态设置rmarkdown中的ggigraph工具提示的内容。
原因:使用嵌入式png的工具提示可以成为图形,这对文本不足的某些生物结构很有价值。以下是我目前正在做的一个最简单的例子:
encodedImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAUCAIAAAAcIrrpAAAACXBIWXMAAASdAAAEnQF8NGuhAAADGElEQVR4nI2Uy08TURTG+VuMJmCCoIKIxq2ujEQT9y40yKsiILrSGITIzoVxZUwDFQlKQiC0ttMpMwXsi9JSSkvftJ0WWkuhBVtoAb+ZKeNQy+PkZjJz5t7fPfec892yg1K2u7u7tbW1vr4ejUYDgYDL5fJ4PHhhGCYej+NXyVWwsqLvnZ0dULAsFAphvdfrBcvhcNjt9oWFhfn5eZPJpNfr8b62tra/v38sLpPJxGIxTML+q6urIAaDQZ/P53a7nU4ncFar1Ww2G41GnU43MzND0/T09DR2LYHb3t4OcxaJRAQiPq2u8KI36vDHXKGEJ5xkX/yMPxCYm5sjSVKlUikUCmx5BIdcrHCGcIBAXCBig3w+X95E1HVR4nG9i7rWSd3opls+mX+ZrJOTkxMTE8hsAYc1vkPz+/2AIsBcLsf/vtKuOfdEWXJcaFTdeTPLMJHx8fGxsTFknMVtbGwgOx7OkHhEhw2E4E/AYZQ3E8Na9iijo6M2m43FIZfLnKGC4KZSKXFqBVxFs/rRB/PDfuP9PgPOe75RxfsbevWYRlEUksjigHBwhvIBKg5NjKvvpgVnNJm9+nyK9996pYUHJxsZGWFxSPySyI7DIf3h35lg/A+en4mVKgnJ++/26DANJyMIgsVtbm4ucmbjLJFIlMRVtpIoa23HFJ6VbaRQjfc/3JimVCoRCovb29vDm5Uzi8WCU0MYZyxF/Qs6nclDPENDQ+l0utB30AOig4DQ9OhPcNF0J+NqO6l77/RMIgO1DA4OouePqCKbzUKGEJDBYIAkISOUBVUWcOXNaqSp5rAC1c80PTITOm5gYAASKhbZASd+hA0W9KjVajUaDTJyqZXg19d1aHC7qHVL1ZKC52KT/Mt3dTKZFOe6+EaBHiA1EKFHuVxe2fKTX3y5TS6TyaRSaXv/14qnCt55+/Vs0fJiHG+4eZA+XDDVEjW/sqZdjcZEzyOchl5dodxtJGGNn477v7LiNrYHU8gd77/5khZfeqfgqiQlcLAHfQZBtlIyeFbc448WSBWjZ3hZ7HeG07wf4+23f7/+An2Gx2N7QYsiAAAAAElFTkSuQmCC"
g = ggplot()+
geom_point_interactive(aes(x=1,y=1,tooltip=sprintf('<img src="%s" />',encodedImage)))
girafe(code=print(g))
这样做的缺点是,对于每次使用工具提示图形的打印,都会重复编码的图像,导致文件大小过大,无法存储许多图像。
方法:为了缓解随着工具提示使用量的增加而增加的文件大小,我希望将嵌入的图像文本分配到json对象中,然后使用javascript动态更新所有工具提示,使其成为嵌入的图像。
我所做的事情:我可以通过简单地包含脚本标记并在这些标记中输出json文本来获得存储在json中的嵌入图像。为了测试这里的硬编码示例,用一个简单的替换文本:
<script type="application/json" id="lookuptable">
{"ID1":"ReplaceText"}
</script>
我不能做的是替换工具提示的文本。从本质上讲,我计划将工具提示设置为某种类型的ID,并使用它将嵌入的图像匹配到相应的点。工具提示文本通过ggigraph存储在json中,类似于:
<script type="application/json" data-for="htmlwidget-b8ceca7828d4dd46f692"> {x:{"html":.....}}</script>
在这个json中,所有html组件(<,",>等(都是;逃脱,";我相信";htmlwidget";数据被传递到基本上是嵌入在html页面中的迷你html页面;htmlwidget";。
我已经尝试将我的临时工具提示包装在<div>标记,但由于它们被绑定在JSON中,因此在DOM中看不到它们。
我只是天真地尝试替换任何脚本标记中ID的所有实例:
<script type="application/javascript">
console.log(document.getElementById('lookuptable').innerHTML)
var lookuptable = JSON.parse(document.getElementById('lookuptable').innerHTML);
var scriptTags = document.getElementsByTagName("script");
for (s=0; s < scriptTags.length; s++){
var item = scriptTags[s];
for(var k in lookuptable){
console.log(item.innerHTML);
item.innerHTML.replace(k,lookuptable[k])
}
}
</script>
然而,当这个脚本运行时,json中似乎不再有工具提示文本(尽管它在html源代码中(。
这就是我目前的困境。如果我有任何进展,我会更新或回答这个问题。
此外,我很清楚这对Shiny来说是微不足道的,不幸的是,这不是一个选项,因为html页面需要完全独立,因为我正在构建的真正的rmarkdown是一个独立的报告。
最后,这里是一个完整的,可重复的例子。最终编织的项目应该导致工具提示为";替换文本";(通过删除\修复R代码块(:
---
title: "Demo"
author: "Zachary Klamer"
date: "12/9/2021"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ggplot2)
library(ggiraph)
library(rjson)
```
```{r,echo=FALSE}
lookup = list()
lookup$FullID1 = "ReplaceText"
jsonData = toJSON(lookup)
```
<script type="application/json" id="lookuptable">
`r jsonData`
</script>
```{r,echo=FALSE}
g = ggplot()+
geom_point_interactive(aes(x=1,y=1,tooltip='FullID1'))
girafe(code=print(g))
```
<script type="application/javascript">
console.log(document.getElementById('lookuptable').innerHTML)
var lookuptable = JSON.parse(document.getElementById('lookuptable').innerHTML);
var scriptTags = document.getElementsByTagName("script");
for (s=0; s < scriptTags.length; s++){
var item = scriptTags[s];
for(var k in lookuptable){
console.log(item.innerHTML);
item.innerHTML.replace(k,lookuptable[k])
}
}
</script>
实现这一目标可能有几种不同的方法,特别是我怀疑使用htmlwidgets"onRender";函数可能能够更干净地实现这一点,但我从未做到这一点。
我发现,对htmlwidget或htmlwidget数据的innerHTML的任何编辑都会完全破坏mouseover文本,因为它会破坏为mouseover文字供电的事件侦听器。
相反,我发现我可以通过将我的结束脚本包装在$(window(.load(function(({…}(调用中来编辑htmlwidget的svg结果。如果我找到所有svg元素(在本例中为圆形!(并编辑这些svg对象的title属性,我可以保留事件侦听器并更改标题内容(成为图像!(。
请参阅下面的完整示例,其中有1000个1kb的图像作为工具提示,但没有增加文件大小:
---
title: "Demo"
author: "Zachary Klamer"
date: "12/9/2021"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ggplot2)
library(ggiraph)
library(rjson)
library(htmlwidgets)
```
```{r,echo=FALSE}
lookup = list()
lookup$FullID1 = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAUCAIAAAAcIrrpAAAACXBIWXMAAASdAAAEnQF8NGuhAAADGElEQVR4nI2Uy08TURTG+VuMJmCCoIKIxq2ujEQT9y40yKsiILrSGITIzoVxZUwDFQlKQiC0ttMpMwXsi9JSSkvftJ0WWkuhBVtoAb+ZKeNQy+PkZjJz5t7fPfec892yg1K2u7u7tbW1vr4ejUYDgYDL5fJ4PHhhGCYej+NXyVWwsqLvnZ0dULAsFAphvdfrBcvhcNjt9oWFhfn5eZPJpNfr8b62tra/v38sLpPJxGIxTML+q6urIAaDQZ/P53a7nU4ncFar1Ww2G41GnU43MzND0/T09DR2LYHb3t4OcxaJRAQiPq2u8KI36vDHXKGEJ5xkX/yMPxCYm5sjSVKlUikUCmx5BIdcrHCGcIBAXCBig3w+X95E1HVR4nG9i7rWSd3opls+mX+ZrJOTkxMTE8hsAYc1vkPz+/2AIsBcLsf/vtKuOfdEWXJcaFTdeTPLMJHx8fGxsTFknMVtbGwgOx7OkHhEhw2E4E/AYZQ3E8Na9iijo6M2m43FIZfLnKGC4KZSKXFqBVxFs/rRB/PDfuP9PgPOe75RxfsbevWYRlEUksjigHBwhvIBKg5NjKvvpgVnNJm9+nyK9996pYUHJxsZGWFxSPySyI7DIf3h35lg/A+en4mVKgnJ++/26DANJyMIgsVtbm4ucmbjLJFIlMRVtpIoa23HFJ6VbaRQjfc/3JimVCoRCovb29vDm5Uzi8WCU0MYZyxF/Qs6nclDPENDQ+l0utB30AOig4DQ9OhPcNF0J+NqO6l77/RMIgO1DA4OouePqCKbzUKGEJDBYIAkISOUBVUWcOXNaqSp5rAC1c80PTITOm5gYAASKhbZASd+hA0W9KjVajUaDTJyqZXg19d1aHC7qHVL1ZKC52KT/Mt3dTKZFOe6+EaBHiA1EKFHuVxe2fKTX3y5TS6TyaRSaXv/14qnCt55+/Vs0fJiHG+4eZA+XDDVEjW/sqZdjcZEzyOchl5dodxtJGGNn477v7LiNrYHU8gd77/5khZfeqfgqiQlcLAHfQZBtlIyeFbc448WSBWjZ3hZ7HeG07wf4+23f7/+An2Gx2N7QYsiAAAAAElFTkSuQmCC" />'
jsonData = toJSON(lookup)
```
<script type="application/json" id="lookuptable">
`r jsonData`
</script>
```{r,echo=FALSE}
g = ggplot()+
geom_point_interactive(aes(x=1:1000,y=1:1000,tooltip='FullID1'))
girafe(code=print(g))
```
<script type="application/javascript">
$(window).load(function(){
var lookuptable = JSON.parse(document.getElementById('lookuptable').innerHTML);
var keys = Object.keys(lookuptable);
var circleTags = document.getElementsByTagName("circle");
for (s=0; s < circleTags.length; s++){
var item = circleTags[s];
var itemTitle = item.attributes.title.nodeValue;
console.log(itemTitle);
if (keys.includes(itemTitle)){
item.attributes.title.nodeValue=lookuptable[itemTitle];
}
console.log(item.attributes.title.nodeValue);
}
});
</script>