As i the title says. I would like to zoom interactively on Sankey networks, as it is for example possible for Force networks. I assume that it would work by adding a htmlwidgets::onRender()
call, containing JS()
.
I would like to do so via a wrapper around sankeyNetwork()
as i have done (badly) with a custom hover tooltip. When i try to use this aproach for zooming i get a lot of uncaught errors; I am a JS noob.
My code is a mess and my question is so general that I belive that no reprex is necessary. If it is necessary, please ask.
Example of (bad) wrapper:
sankeyNetworkWithAge <- function(Links, Nodes, Source, Target, Value,
NodeID, NodeGroup = NodeID,
LinkGroup = NULL, ...) {
# Print debug information
print("Creating base widget...")
# Create the base widget with tryCatch to catch any errors
widget <- tryCatch({
sankeyNetwork(
Links = Links,
Nodes = Nodes,
Source = Source,
Target = Target,
Value = Value,
NodeID = NodeID,
NodeGroup = NodeGroup,
LinkGroup = LinkGroup,
...
)
}, error = function(e) {
print(paste("Error creating widget:", e$message))
return(NULL)
})
# Check if widget creation was successful
if (is.null(widget)) {
stop("Failed to create base widget")
}
print("Adding custom data...")
# Add custom data
widget$x$options$median_age <- Links$median_age
print("Adding custom JavaScript...")
# Add custom JavaScript
widget <- htmlwidgets::onRender(
widget,
'
function(el, x) {
console.log("Running custom JavaScript");
var medianAges = x.options.median_age;
d3.select(el)
.selectAll(".link")
.each(function(d, i) {
d.median_age = medianAges[i];
})
.select("title")
.text(function(d) {
return d.source.name + " → " + d.target.name + "\\n" +
d.value + " Candidates\\n" +
"Median Age: " + d.median_age;
});
}
'
)
print("Returning widget...")
return(widget)
}
I wouldn't say I recommend this, but here you go...
library(networkD3)
URL <- paste0(
"https://cdn.rawgit.com/christophergandrud/networkD3/",
"master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)
widget <- sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
units = "TWh", fontSize = 12, nodeWidth = 30)
widget <- htmlwidgets::onRender(
widget,
'
function(el, x) {
var zoom = d3.zoom();
function redraw() {
d3.select(el).select("g")
.attr("transform", d3.event.transform);
}
zoom.on("zoom", redraw);
d3.select(el).select("svg")
.attr("pointer-events", "all")
.call(zoom);
}
'
)
print(widget)