简体   繁体   中英

How to change the colors of nodes in force directed graph in d3js using javascript?

Current Behavior: All the nodes are in random colors.

Expected Behavior: All the parent nodes should be in same colors(blue for example) and all the child nodes should in same colors(light blue).

How to achieve this ?

Here is the working jsfiddle: Fiddle

  var color = d3.scaleOrdinal(d3.schemeCategory10);

grads = svg.append("defs").selectAll("radialGradient")
    .data(graph.nodes)
    .enter()
    .append("radialGradient")
    .attr("gradientUnits", "objectBoundingBox")
    .attr("cx", 0)
    .attr("fill", function(d) { return color(d.id); })
    .attr("cy", 0)
    .attr("r", "100%")
    .attr("id", function(d, i) { return "grad" + i; });

 grads.append("stop")
    .attr("offset", "0%")
    .style("stop-color", "white");

 grads.append("stop")
    .attr("offset", "100%")
    .style("stop-color",  function(d) { return color(d.id); });  

nodeElements =  g.append("g")
  .attr("class", "nodes")
  .selectAll("circle")
  .data(graph.nodes)
  .enter().append("circle")
  .attr("r", 60)

  .attr("stroke", "#fff")
  .attr('stroke-width', 21)
  .attr("id", function(d) { return d.id })
   //.attr("fill", function(d) {return color(d.id)}) 
     .attr('fill', function(d, i) { return 'url(#grad' + i + ')'; })

Then you need to change the color based on the group. Change this line as follow:

.attr("fill", function(d) {return color(d.group)})

Please find the working code below:

 var graph = { 'nodes': [{ 'id': 'Material_Definition', 'group': 0 }, { 'id': 'Item1', 'group': 1 }, { 'id': 'Item2', 'group': 1 }, { 'id': 'Item3', 'group': 1 }, { 'id': 'Item4', 'group': 1 }, { 'id': 'Item5', 'group': 1 }, { 'id': 'SubItem1_Item1', 'group': 2 }, { 'id': 'SubItem2_Item1', 'group': 2 } ], 'links': [ /* Material Definition linked to Items */ { 'source': 'Material_Definition', 'target': 'Item1', 'value': 1, 'type': 'A' }, { 'source': 'Material_Definition', 'target': 'Item2', 'value': 8, 'type': 'A' }, { 'source': 'Material_Definition', 'target': 'Item3', 'value': 10, 'type': 'A' }, { 'source': 'Material_Definition', 'target': 'Item3', 'value': 1, 'type': 'A' }, { 'source': 'Material_Definition', 'target': 'Item4', 'value': 1, 'type': 'A' }, { 'source': 'Material_Definition', 'target': 'Item5', 'value': 1, 'type': 'A' }, /* Item1 is linked to SubItems */ { 'source': 'Item1', 'target': 'SubItem1_Item1', 'value': 2, 'type': 'A' }, { 'source': 'Item1', 'target': 'SubItem2_Item1', 'value': 1, 'type': 'A' }, /* Interconnected Items */ { 'source': 'Item5', 'target': 'Item4', 'value': 2, 'type': 'A' }, { 'source': 'Item2', 'target': 'Item3', 'value': 1, 'type': 'A' }, ] }; var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height") var store = Object.assign({}, graph); var color = d3.scaleOrdinal(d3.schemeCategory10); var zoom_handler = d3.zoom().on("zoom", zoom_actions); var linkElements, nodeElements, textElements, grads; // zoom_handler(svg); var simulation = d3.forceSimulation() .force("link", d3.forceLink().distance(700).id(function(d) { return d.id; })) .force("charge", d3.forceManyBody().strength(-1000)) .force("center", d3.forceCenter(width / 2, height / 2)); var g = svg.append("g") .attr("class", "everything"); svg.call(zoom_handler) .call(zoom_handler.transform, d3.zoomIdentity.translate(200, 150).scale(0.2)); linkElements = svg.append("g").selectAll(".link"), nodeElements = svg.append("g").selectAll(".nodes"); grads = svg.append("g").selectAll(".grads"); textElements = svg.append("g").selectAll(".texts"); drawGraph(); function drawGraph() { // empty current Graph contents g.html('') grads = svg.append("defs").selectAll("radialGradient") .data(graph.nodes) .enter() .append("radialGradient") .attr("gradientUnits", "objectBoundingBox") .attr("cx", 0) .attr("fill", function(d) { return color(d.group); }) .attr("cy", 0) .attr("r", "100%") .attr("id", function(d, i) { return "grad" + i; }); grads.append("stop") .attr("offset", "0%") .style("stop-color", "white"); grads.append("stop") .attr("offset", "100%") .style("stop-color", function(d) { return color(d.id); }); linkElements = g.append("g") .attr("class", "links") .selectAll("line") .data(graph.links) .enter().append("line") .style("stroke-width", 5.5) .style("stroke", "grey") nodeElements = g.append("g") .attr("class", "nodes") .selectAll("circle") .data(graph.nodes) .enter().append("circle") .attr("r", 60) .attr("stroke", "#fff") .attr('stroke-width', 21) .attr("id", function(d) { return d.id }) .attr("fill", function(d) { return color(d.group) }) /* .attr('fill', function(d, i) { return 'url(#grad' + i + ')'; }) */ .on('contextmenu', function(d) { d3.event.preventDefault(); menu(d3.mouse(svg.node())[0], d3.mouse(svg.node())[1]); }) .on('mouseover', selectNode) .on('mouseout', releaseNode) .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); textElements = g.append("g") // use g.append instead of svg.append to enable zoom .attr("class", "texts") .selectAll("text") .data(graph.nodes) .enter().append("text") .attr("text-anchor", "end") .text(function(node) { return node.id }) .attr("font-size", 55) .attr("font-family", "sans-serif") .attr("fill", "black") .attr("style", "font-weight:bold;") .attr("dx", 30) .attr("dy", 80) } function ticked() { linkElements .attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); nodeElements .attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }) .each(d => { d3.select('#t_' + d.id).attr('x', dx + 10).attr('y', dy + 3); }); textElements .attr('x', function(d) { return dx }) .attr('y', function(d) { return dy }); } simulation .nodes(graph.nodes) .on("tick", ticked); simulation.force("link") .links(graph.links); function zoom_actions() { g.attr("transform", d3.event.transform) } function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = dx; d.fy = dy; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } function selectNode(selectedNode) { var neighbors = getNeighbors(selectedNode) nodeElements.transition().duration(500) .attr('r', function(node) { return getNodeRadius(node, neighbors); }); nodeElements.attr('fill', function(node) { return getNodeColor(node, neighbors, selectedNode); }) textElements.transition().duration(500).style('font-size', function(node) { return getTextColor(node, neighbors) }) } function releaseNode() { nodeElements.transition().duration(500) .attr('r', 60); nodeElements.attr('fill', function(d, i) { return 'url(#grad' + i + ')'; }) linkElements.style('stroke', 'grey'); } function getNeighbors(node) { return graph.links.reduce(function(neighbors, link) { if (link.target.id === node.id) { neighbors.push(link.source.id) } else if (link.source.id === node.id) { neighbors.push(link.target.id) } return neighbors }, [node.id]) } function getNodeColor(node, neighbors, selectedNode) { // If is neighbor if (Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1) { return 'url(#grad' + selectedNode.index + ')' // return node.level === 1 ? '#9C4A9C' : 'rgba(251, 130, 30, 1)' } else { return 'url(#grad' + node.index + ')' } //return node.level === 0 ? '#91007B' : '#D8ABD8' } function getNodeRadius(node, neighbors) { // If is neighbor if (neighbors.indexOf(node.id) > -1) { return '100' } else { return '60' } } function isNeighborLink(node, link) { return link.target.id === node.id || link.source.id === node.id } function getTextColor(node, neighbors) { return Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1 ? '40px' : '25px' } var filter = document.querySelector('#filter'); filter.addEventListener('change', function(event) { filterData(event.target.value); drawGraph(); }) var resetFilter = document.querySelector('#reset'); resetFilter.addEventListener('click', function(event) { drawGraph(); }) function filterData(id) { graph = Object.assign({}, store); graph.nodes = []; graph.links = []; dummyStore = [id]; store.links.forEach(function(link) { if (link.source.id === id) { graph.links.push(link); dummyStore.push(link.target.id); } else if (link.target.id === id) { graph.links.push(link); dummyStore.push(link.source.id) } }); store.nodes.forEach(function(node) { if (dummyStore.includes(node.id)) { graph.nodes.push(node); } }) }
 .links line { stroke: #999; stroke-opacity: 0.6; } .nodes circle { stroke: #000; stroke-width: 1.5px; } text { font-size: 10px; }
 <script src="https://d3js.org/d3.v4.min.js"></script> Filter: <input type="text" name="filter" id="filter" /> <button id='reset'>Reset Filter</button> <svg width="798" height="400"></svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM