score:1

Accepted answer

I tried editing your code and was able to achieve this. To update the data, we need to make use of enter, update and exit methods. In v3 I remember, when we enter the new data and this will create any missing links or nodes and using exit(), we can remove nodes, links which are not present. After enter, we append the new nodes,links and later update its attributes. We can actually use the same function to create and update which you can try. I dont know why the newDataB is not coming as node in below function. Something wrong with my sample data it seems. Your new sample data is working fine with below code.

var diameter = 760,
  radius = diameter / 2;
innerRadius = radius - 160;

var cluster = d3.cluster()
  .size([360, innerRadius]);

var line = d3.radialLine()
  .curve(d3.curveBundle.beta(0.85))
  .radius(function(d) {
    return d.y;
  })
  .angle(function(d) {
    return d.x / 180 * Math.PI;
  });

var svg = d3.select("body").append("svg")
  .attr("width", diameter)
  .attr("height", diameter)
  .append("g")
  .attr("transform", "translate(" + radius + "," + radius + ")");

var link = svg.append("g").selectAll(".link"),
  node = svg.append("g").selectAll(".node");

switchData(1);

function mouseovered(d) {
  node
    .each(function(n) {
      n.target = n.source = false;
    });

  link
    .classed("link--target", function(l) {
      if (l.target === d) return l.source.source = true;
    })
    .classed("link--source", function(l) {
      if (l.source === d) return l.target.target = true;
    })
    .filter(function(l) {
      return l.target === d || l.source === d;
    })
    .raise();
  node
    .classed("node--target", function(n) {
      return n.target;
    })
    .classed("node--source", function(n) {
      return n.source;
    });
}

function mouseouted(d) {
  link
    .classed("link--target", false)
    .classed("link--source", false);

  node
    .classed("node--target", false)
    .classed("node--source", false);
}

// Lazily construct the package hierarchy from class names.
function packageHierarchy(classes) {
  var map = {};

  function find(name, data) {
    var node = map[name],
      i;
    if (!node) {
      node = map[name] = data || {
        name: name,
        children: []
      };
      if (name.length) {
        node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
        node.parent.children.push(node);
        node.key = name.substring(i + 1);
      }
    }
    return node;
  }

  classes.forEach(function(d) {
    find(d.name, d);
  });

  return d3.hierarchy(map[""]);
}

// Return a list of imports for the given array of nodes.
function packageImports(nodes) {
  var map = {},
    imports = [];

  // Compute a map from name to node.
  nodes.forEach(function(d) {
    map[d.data.name] = d;
  });

  // For each import, construct a link from the source to target node.
  nodes.forEach(function(d) {
    if (d.data.imports) d.data.imports.forEach(function(i) {
      imports.push(map[d.data.name].path(map[i]));
    });
  });

  return imports;
}

// update data function
function updateData(classes) {

  var root = packageHierarchy(classes);

  cluster(root);

  var nodes = root.leaves();
  var links = packageImports(root.leaves());

  let link = svg.selectAll('.link').data(links);

  link.enter().append("g")
    .attr("class", "link").append("path").each(function(d) {
      d.source = d[0], d.target = d[d.length - 1];
    });
  svg.selectAll('path').attr("class", "link").transition()
    .duration(1000).attr("d", line);
  link.exit().remove();

  let node = svg.selectAll('.node').data(nodes);
  node.enter().append('g').append("text");
  svg.selectAll('text').attr("transform", function(d) {
      return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)");
    })
    .attr("text-anchor", function(d) {
      return d.x < 180 ? "start" : "end";
    })
    .attr("class", "node")
    .attr("dy", ".31em")
    .text(function(d) {
      return d.data.key;
    });


  node.exit().remove();

}

function switchData(dataset) {
  let classes = [];
  if (dataset == 0) {
    classes = [{
        "name": "flare.A.newdataA",
        "size": 1000,
        "imports": [
          "flare.B.newdataB"

        ]
      },
      {
        "name": "flare.B.newdataB",
        "size": 1400,
        "imports": [
          "flare.A.newdataA"
        ]
      },
      {
        "name": "flare.A.newdataC",
        "size": 1200,
        "imports": [
          "flare.A.newdataA", "flare.B.newdataB"
        ]
      }
    ];


  } else

  {
    classes = [{
        "name": "flare.A.dataA",
        "size": 1000,
        "imports": [
          "flare.B.dataB"

        ]
      },
      {
        "name": "flare.B.dataB",
        "size": 1200,
        "imports": [
          "flare.A.dataA"
        ]
      }
    ];

  }

  updateData(classes)

}
<!DOCTYPE html>
<html>

<head>

  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

  <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'></script>

  <script src="https://d3js.org/d3.v5.js"></script>

  <style>
    .node {
      font: 300 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
      fill: rgb(0, 0, 0, .6);
    }
    
    .link {
      stroke: steelblue;
      fill: none;
      pointer-events: none;
    }
  </style>

</head>

<body>

  <div class="grid-container"></div>

  <div class="grid-item" id="chart">

    <div id="my_dataviz"></div>
  </div>

  </div>


</body>


<div id="option">
  <input name="updateButton" type="button" value="Update" onclick="switchData(0)" />
</div>
<div id="option">
  <input name="updateButton" type="button" value="SwitchBack" onclick="switchData(1)" />
</div>


</html>

score:0

Try with this:

transition().duration(1000)
                .ease("elastic")
                .call(draw);

from D3 transitions on enter/update/remove

Also

D3.js update with transition


Related Query

More Query from same tag