簡體   English   中英

R ggiraph 在沒有 Shiny 的情況下動態設置工具提示文本

[英]R ggiraph dynamically setting tooltip text without Shiny

內容:在頁面加載時將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))

這樣做的缺點是,對於使用工具提示圖形的每個 plot,編碼的圖像都會重復,導致文件太大而無法存儲許多文件。

如何:為了減輕文件大小隨着工具提示使用的增加而增加的問題,我希望將嵌入圖像文本分配到 json object,然后使用 ZDE9B9ED78D7E2E19DCEEFFEE780E2 動態更新所有工具提示以成為嵌入圖像。

我已經完成的事情:我可以通過簡單地包含腳本標簽並在這些標簽中輸出 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”數據被傳遞給嵌入在 ZFC35FDC70D5FC69D269883A82E2 中的基本上是一個 mini-html 頁面的頁面。

我嘗試將我的臨時工具提示包裝在 <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 是一個獨立的報告。

最后,這是一個完整的、可重復的示例。 最終的針織項目應導致工具提示為“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>

可能有幾種不同的方法可以實現這個目標,特別是我懷疑使用 htmlwidgets "onRender" function 可能能夠更干凈地實現這個目標,但我從來沒有讓它工作。

我發現,對 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM