R语言中使用foreignObject实现Sankeynetwork文本居中对齐
直接修改onRender里的JS逻辑即可,问题根源是之前写死了foreignObject的宽高和定位,没有和节点的实际坐标、尺寸匹配,同时插入的标签内容没加居中样式。调整后完整可运行代码如下:
library(networkD3) library(htmlwidgets) library(data.table) set.seed(1999) links <- data.table( src = rep(0:4, times=c(1,1,2,3,5)), target = sample(1:11, 12, TRUE), value = sample(100, 12) )[src < target, ] # 避免自环 nodes <- data.table(name=LETTERS[1:12]) ## 给标签加统计值 txt <- links[, .(total = sum(value)), by=c('target')] nodes[txt$target+1L, name := paste0(name, '<br>(', txt$total, ')')] ## 绘制桑基图 sn <- sankeyNetwork(Links=links, Nodes=nodes, Source='src', Target='target', Value='value', NodeID='name', fontSize=16, nodeWidth=50, width=600, height=300) onRender(sn, ' function(el,x) { // 移除默认文本标签 d3.selectAll(".node text").remove() d3.selectAll(".node") .append("foreignObject") // 匹配节点实际位置、尺寸,避免偏移 .attr("x", function(d) { return d.x; }) .attr("y", function(d) { return d.y; }) .attr("width", function(d) { return d.dx; }) .attr("height", function(d) { return d.dy; }) // 插入带居中样式的标签内容 .html(function(d) { return `<div style="width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; font-size: 16px; line-height: 1.2;"> ${d.name} </div>` }) } ' )
核心调整点:
- 去掉了之前写死的
width=100、height=50固定值,直接读取每个节点自身的左上角坐标(d.x/d.y)和自适应尺寸(d.dx为节点宽度、d.dy为节点高度)设置foreignObject属性,让标签容器和节点框完全重合。 - 在foreignObject内部嵌套占满全容器的div,用flex布局实现容器内内容的水平、垂直双向居中,同时给div加
text-align: center属性,保证两行文本自身也保持居中对齐,字号、行高和初始设置的fontSize参数匹配即可。
运行后标签会完全贴合节点框实现双向居中,内部两行文字也会保持居中对齐。
内容的提问来源于stack exchange,提问作者Ai4l2s
相关产品推荐
相关产品推荐

