nyi
nyi

Reputation: 3229

Setting the color of the nodes in d3

I am playing with a D3 example Force Dragging on bl.ocks.org.

I am loading the nodes from JSON file, but I am not able to figure out on how to set the color of the nodes (initially any color but ideally I would like to provide the color of the nodes in the JSON).

Code : (copied from bl.ocks.org)

var canvas = document.querySelector("canvas"),
    context = canvas.getContext("2d"),
    width = canvas.width,
    height = canvas.height;

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("../data/prc_network.json", function(error, graph) {
  if (error) throw error;

  simulation
      .nodes(graph.nodes)
      .on("tick", ticked);

  simulation.force("link")
      .links(graph.links);

  d3.select(canvas)
      .call(d3.drag()
          .container(canvas)
          .subject(dragsubject)
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));

  function ticked() {
    context.clearRect(0, 0, width, height);

    context.beginPath();
    graph.links.forEach(drawLink);
    context.strokeStyle = "#aaa";
    context.stroke();

    context.beginPath();
    graph.nodes.forEach(drawNode);
    context.fill();
    context.strokeStyle = "#fff";
    context.stroke();
  }

  function dragsubject() {
    return simulation.find(d3.event.x, d3.event.y);
  }
});

function dragstarted() {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d3.event.subject.fx = d3.event.subject.x;
  d3.event.subject.fy = d3.event.subject.y;
}

function dragged() {
  d3.event.subject.fx = d3.event.x;
  d3.event.subject.fy = d3.event.y;
}

function dragended() {
  if (!d3.event.active) simulation.alphaTarget(0);

}

function drawLink(d) {
  context.moveTo(d.source.x, d.source.y);
  context.lineTo(d.target.x, d.target.y);
}

function drawNode(d) {
  context.moveTo(d.x + 3, d.y);
  context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
}

</script>

Upvotes: 3

Views: 1796

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38231

You need to start a new path each time you want to color one node - as each path has a set styling. To do this we need to move all the node drawing portions to the drawNode function as opposed to the tick function so that we can style each node individually:

function drawNode(d) {
  context.beginPath(); 
  context.moveTo(d.x + 3, d.y);
  context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
  context.fillStyle = d.color // or some other property that has a valid color
  context.fill();
  context.strokeStyle = "#fff";
  context.stroke();
}

We can also use a scale to take some property and convert it to a color:

var colors = d3.scaleOrdinal().range(d3.schemeCategory20);

function drawNode(d) {
  context.beginPath(); 
  context.moveTo(d.x + 3, d.y);
  context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
  context.fillStyle = colors(d.property);
  context.fill();
  context.strokeStyle = "#fff";
  context.stroke();
}

Here's a block using the base example (with the base data) coloring for node group.

Upvotes: 2

Related Questions