You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R Markdown标签页中非首个桑基图的htmlwidgets::onRender失效问题

Hey there! Let’s work through your two Sankey plot issues in R Markdown—first getting htmlwidgets::onRender to work for plots in non-initial tabs, then controlling those node labels exactly how you want.

Fixing onRender for Tabbed Sankey Plots

The problem happens because only the first active tab’s content gets rendered into the DOM when your HTML document loads. Plots in inactive tabs are hidden, so the onRender callback can’t find their elements to apply your custom adjustments. Here’s a solid fix:

  1. Assign unique IDs to each Sankey plot: Use the elementId parameter in sankeyNetwork to give every plot a distinct identifier.
  2. Listen for tab activation: Use Bootstrap’s tab events (since R Markdown uses Bootstrap tabs) to trigger your custom JavaScript only when the tab containing the plot becomes visible.

Here’s how to implement this in your code:

---
title: "Sankey Tabs Fix"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(networkD3)
library(htmlwidgets)

# Sample data (replace with your actual nodes/links)
nodes1 <- data.frame(name = c("A", "B", "C"))
links1 <- data.frame(source = c(0,1), target = c(2,2), value = c(10,20))

nodes2 <- data.frame(name = c("X", "Y", "Z"))
links2 <- data.frame(source = c(0,1), target = c(2,2), value = c(15,25))

Sankey Plots in Tabs

tabsetPanel(
  tabPanel("First Plot",
           sankeyNetwork(Links = links1, Nodes = nodes1, Source = "source",
                         Target = "target", Value = "value", NodeID = "name",
                         elementId = "sankey-plot-1") %>%
             onRender("function(el, x) {
               // Apply adjustments immediately since this is the initial active tab
               d3.select(el).selectAll('.node text')
                 .style('font-size', '12px')
                 .attr('x', x.nodeWidth + 8);
             }")
  ),
  tabPanel("Second Plot",
           sankeyNetwork(Links = links2, Nodes = nodes2, Source = "source",
                         Target = "target", Value = "value", NodeID = "name",
                         elementId = "sankey-plot-2") %>%
             onRender("function(el, x) {
               var tabPane = $(el).closest('.tab-pane');
               
               // If tab isn't active yet, wait for it to be shown
               if (!tabPane.hasClass('active')) {
                 tabPane.one('shown.bs.tab', function() {
                   // Your custom adjustments here
                   d3.select(el).selectAll('.node text')
                     .style('font-size', '12px')
                     .attr('x', x.nodeWidth + 8);
                 });
               } else {
                 // Tab is already active, apply changes right away
                 d3.select(el).selectAll('.node text')
                   .style('font-size', '12px')
                   .attr('x', x.nodeWidth + 8);
               }
             }")
  )
)
### Controlling Node Labels
You have two options here—quick R-side adjustments, or more flexible control with JavaScript.

#### Option 1: R-Side Control (Simple)
- **Change label text**: Modify the `name` column in your `nodes` data frame to set custom labels:
  ```r
  nodes$name <- paste("Category:", nodes$name) # Add a prefix to all labels
  • Adjust font size: Use the fontSize parameter in sankeyNetwork to set label size globally:
    sankeyNetwork(..., fontSize = 14) # Larger 14px font for all labels
    

Option 2: Advanced Control with JavaScript (via onRender)

For precise control over label position, alignment, or conditional styling, use D3 in your onRender callback:

sankeyNetwork(...) %>%
  onRender("function(el, x) {
    // Move labels to the right of left nodes, left of right nodes
    d3.select(el).selectAll('.node text')
      .attr('x', function(d) {
        // Align based on node position relative to plot center
        return d.x < x.width / 2 ? x.nodeWidth + 10 : -10;
      })
      .attr('text-anchor', function(d) {
        return d.x < x.width / 2 ? 'start' : 'end';
      })
      .style('fill', '#2c3e50') // Dark gray text color
      .style('font-weight', '600'); // Semi-bold labels
  }")

内容的提问来源于stack exchange,提问作者Yorgos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:24:36