【问题标题】:R ggiraph dynamically setting tooltip text without ShinyR ggiraph 动态设置工具提示文本没有闪亮
【发布时间】:2021-12-09 18:28:12
【问题描述】:

什么:在页面加载时动态设置 rmarkdown 中的 ggiraph 工具提示内容为 html。

为什么:使用嵌入式 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,并使用它来将嵌入的图像与相应的点相匹配。工具提示文本由 ggiraph 存储在 json 中,如下所示:

<script type="application/json" data-for="htmlwidget-b8ceca7828d4dd46f692"> {x:{"html":.....}}</script>

在这个 json 中,所有的 html 组件(,等等)都被“转义”了,我相信这个“​​htmlwidget”数据被传递到一个嵌入在 html 页面中的 mini-html 页面,“htmlwidget” ”。

我尝试将我的临时工具提示包装在

标记中,但由于它们被绑定在 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 是一个独立的报告。

最后,这是一个完整的、可重现的示例。最终的针织项目应导致工具提示为“ReplaceText”(通过删除 \ 来修复 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>

【问题讨论】:

    标签: javascript r htmlwidgets ggiraph


    【解决方案1】:

    可能有几种不同的方法可以实现这个目标,特别是我怀疑使用 htmlwidgets 的“onRender”函数可能能够更干净地实现这个目标,但我从来没有做到这一点。

    我发现,对 htmlwidget 或 htmlwidget 数据的 innerHTML 的任何编辑都会完全破坏鼠标悬停文本,因为它会破坏驱动鼠标悬停文本的事件侦听器。

    相反,我发现我可以通过将结束脚本包装在 $(window).load(function(){ ... }) 调用中来编辑 htmlwidget 生成的 svg。如果我找到所有 svg 元素(在本例中为圆圈!)并编辑这些 svg 对象的标题属性,我可以保留事件侦听器并更改标题内容(成为图像!)。

    请参阅下面的完整示例,其中包含 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>
    

    【讨论】:

      猜你喜欢
      • 2021-05-03
      • 2020-02-18
      • 2013-05-03
      • 1970-01-01
      • 2017-03-15
      • 1970-01-01
      • 2017-03-06
      • 1970-01-01
      相关资源
      最近更新 更多