Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does anyone know how to save a drag and drop graph in Rshiny after drawing a flowchart with visNetwork #467

Open
WSinana opened this issue Apr 27, 2024 · 0 comments

Comments

@WSinana
Copy link

WSinana commented Apr 27, 2024

I want to implement it on the shiny platform to remember the shape of the flow chart after I modify it. When I rename a node each time, its shape will not reset, and I can drag it to my favorite shape and click download to save it to the local png format.

Has anyone dealt with this issue before? If so, could you share how you managed to save and reload the network with the nodes in their new positions? Thank you in advance for your help!

create_flow_chart_with_weights <- function(weight_data, initial_alpha_values) {

nodes <- data.frame(id = 1:nrow(weight_data),
                    label = sapply(1:nrow(weight_data), function(i) {
                      sprintf("H%d\nα=%s", i, formatC(initial_alpha_values[i], format = "g"))
                    }),
                    color = "lightblue",
                    shape = "ellipse",
                    shadow = TRUE)

edges <- data.frame()

added_edges <- matrix(FALSE, nrow = nrow(weight_data), ncol = ncol(weight_data))
for (i in 1:nrow(weight_data)) {
  for (j in 1:ncol(weight_data)) {
    if (!is.na(weight_data[i, j]) && weight_data[i, j] > 0) {
      if (i != j && !is.na(weight_data[j, i]) && weight_data[j, i] > 0 && !added_edges[j, i]) {
     
        added_edges[i, j] <- TRUE
        added_edges[j, i] <- TRUE

        edges <- rbind(edges, data.frame(from = i, to = j, label = formatC(weight_data[i, j], format = "g"), arrows = "to"))
        edges <- rbind(edges, data.frame(from = j, to = i, label = formatC(weight_data[j, i], format = "g"), arrows = "to"))
      } else if (!added_edges[i, j]) {

        added_edges[i, j] <- TRUE
        edges <- rbind(edges, data.frame(from = i, to = j, label = formatC(weight_data[i, j], format = "g"), arrows = "to"))
      }
    }
  }
}
edges$smooth <- mapply(function(from, to) {
  if (added_edges[from, to] && added_edges[to, from]) {
    list(enabled = TRUE, type = "curved", roundness = 0.5)
  } else {
    FALSE
  }
}, edges$from, edges$to, SIMPLIFY = FALSE)

visNetwork(nodes, edges) %>%
visEdges(arrows = 'to', font = list(background = 'white')) %>%
visInteraction(dragNodes = TRUE) %>%
visPhysics(enabled = FALSE,solver = "forceAtlas2Based", forceAtlas2Based = list(springLength = 250, gravitationalConstant = -300, springConstant = 1.0)) %>%
visOptions(highlightNearest = TRUE, nodesIdSelection = FALSE) %>%
visInteraction(zoomView = FALSE) %>%
visLayout(randomSeed = 123)
}
observe({
visNetworkProxy("weightBasedFlowChart") %>%
visStorePositions()
})

proxy <- dataTableProxy('weightTable')
observeEvent(input$weightTable_cell_edit, {
info <- input$weightTable_cell_edit
rv$data[info$row, info$col] <- as.numeric(info$value)

initial_alpha_values <- alpha_table_data()[, "分配的Alpha"]

for (i in 1:nrow(rv$data)) {
  rowSum <- sum(rv$data[i, ], na.rm = TRUE)
  if (rowSum > 1) {
    showModal(modalDialog(
      title = "错误",
      paste0("第 ", i, " 行的数值总和不能超过 1。您当前的和为: ", rowSum),
      easyClose = TRUE,
      footer = NULL
    ))
    rv$data[i, info$col] <- NA_real_ # Reset the value
    break
  }
}


output$weightBasedFlowChart <- renderVisNetwork({
  create_flow_chart_with_weights(rv$data, initial_alpha_values)
})

})

observeEvent(input$renameNodes1, {
if (!is.null(alpha_table_data()) && "分配的Alpha" %in% names(alpha_table_data())) {
initial_alpha_values <- alpha_table_data()[, "分配的Alpha"]
nodes_data <- create_nodes_data_for_weight_based_chart(rv$data, initial_alpha_values)

  nodes_info$names <- nodes_data$name
  
  output$renameTable1 <- renderDT({
    datatable(nodes_data[, c("name", "alpha")], editable = 'cell', options = list(dom = 't'))
  })
}

})

observeEvent(input$renameTable1_cell_edit, {
info <- input$renameTable1_cell_edit
if (!is.null(alpha_table_data()) && "分配的Alpha" %in% names(alpha_table_data())) {
initial_alpha_values <- alpha_table_data()[, "分配的Alpha"]

  if (info$col == 1) {  # “name”列
    nodes_info$names[info$row] <- info$value
  } else if (info$col == 2) {  # “alpha”列
    initial_alpha_values[info$row] <- as.numeric(info$value)
  }
  

  output$weightBasedFlowChart <- renderVisNetwork({
    nodes_data <- create_nodes_data_for_weight_based_chart(rv$data, initial_alpha_values)
    for (i in seq_along(nodes_info$names)) {
      nodes_data$name[i] <- nodes_info$names[i]
      nodes_data$alpha[i] <- initial_alpha_values[i]  
    }
    create_flow_chart_with_weights_custom(nodes_data, rv$data)

  })
}

})

create_nodes_data_for_weight_based_chart <- function(weight_data, initial_alpha_values) {

nodes_data <- data.frame(
  id = 1:nrow(weight_data),
  name = sapply(1:nrow(weight_data), function(i) sprintf("H%d", i)),
  alpha = initial_alpha_values
)

return(nodes_data)

}
create_flow_chart_with_weights_custom <- function(nodes_data, weight_data) {

nodes <- data.frame(
  id = nodes_data$id,
  label = sapply(1:nrow(nodes_data), function(i) {
    sprintf("%s\nα=%s", nodes_data$name[i], formatC(nodes_data$alpha[i], format = "g"))
  }),
  color = "lightblue",
  shape = "ellipse",
  shadow = TRUE
)

edges <- data.frame()
added_edges <- matrix(FALSE, nrow = nrow(weight_data), ncol = ncol(weight_data))

for (i in 1:nrow(weight_data)) {
  for (j in 1:ncol(weight_data)) {
    if (!is.na(weight_data[i, j]) && weight_data[i, j] > 0) {
      if (i != j && !is.na(weight_data[j, i]) && weight_data[j, i] > 0 && !added_edges[j, i]) {

        added_edges[i, j] <- TRUE
        added_edges[j, i] <- TRUE
 
        edges <- rbind(edges, data.frame(from = i, to = j, label = formatC(weight_data[i, j], format = "g"), arrows = "to"))
        edges <- rbind(edges, data.frame(from = j, to = i, label = formatC(weight_data[j, i], format = "g"), arrows = "to"))
      } else if (!added_edges[i, j]) {

        added_edges[i, j] <- TRUE
        edges <- rbind(edges, data.frame(from = i, to = j, label = formatC(weight_data[i, j], format = "g"), arrows = "to"))
      }
    }
  }
}
edges$smooth <- mapply(function(from, to) {
  if (added_edges[from, to] && added_edges[to, from]) {
    list(enabled = TRUE, type = "curved", roundness = 0.5)
  } else {
    FALSE
  }
}, edges$from, edges$to, SIMPLIFY = FALSE)

visNetwork(nodes, edges) %>%
visEdges(arrows = 'to', font = list(background = 'white')) %>%
visInteraction(dragNodes = TRUE) %>%
visPhysics(enabled = FALSE,solver = "forceAtlas2Based", forceAtlas2Based = list(springLength = 250, gravitationalConstant = -300, springConstant = 1.0)) %>%
visOptions(highlightNearest = TRUE, nodesIdSelection = FALSE) %>%
visInteraction(zoomView = FALSE) %>%
visLayout(randomSeed = 123)
}

observeEvent(input$savePositions, {
visNetworkProxy("weightBasedFlowChart") %>% visGetPositions()
})

nodePositions <- reactive({
positions <- input$weightBasedFlowChart_positions
if(!is.null(positions)){
nodePositions <- do.call("rbind", lapply(positions, function(x){ data.frame(x = x$x, y = x$y)}))
nodePositions$id <- names(positions)
nodePositions
} else {
NULL
}
})

output$downloadFlowChart <- downloadHandler(
filename = function() {
paste("weight_flow_chart_", Sys.Date(), ".png", sep = "")
},
content = function(file) {

  updated_alpha_values <- rv$initial_alpha_values
  if (!is.null(alpha_table_data()) && "分配的Alpha" %in% names(alpha_table_data())) {
    updated_alpha_values <- alpha_table_data()[, "分配的Alpha"]
  }
  updated_node_data <- create_nodes_data_for_weight_based_chart(rv$data, updated_alpha_values)
  
  if (!is.null(nodes_info$names)) {
    updated_node_data$name <- nodes_info$names
  }

  if (!is.null(input$nodePositions)) {
    for (id in names(input$nodePositions$x)) {
      if (id %in% updated_node_data$id) {
        updated_node_data$x[updated_node_data$id == id] <- input$nodePositions$x[id]
        updated_node_data$y[updated_node_data$id == id] <- input$nodePositions$y[id]
      }
    }
  }
  

  weight_flow_chart <- create_flow_chart_with_weights_custom(updated_node_data, rv$data)
  

  temp_html_file <- tempfile(fileext = ".html")
  visNetwork::visSave(weight_flow_chart, temp_html_file)
  

  webshot(temp_html_file, file = file, vwidth = 800, vheight = 600)

  unlink(temp_html_file)
}

)`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant