D3 adding and removing nodes with strength

I compiled the following jfiddle based on some code that I saw in the book - http://jsfiddle.net/hiwilson1/o3gwejbx/2 . In general, I follow what is happening, but there are several aspects that I do not observe.

svg.on("mousemove", function () {

    var point = d3.mouse(this), 
        node = {x: point[0], y: point[1]}; 

    svg.append("circle")
        .data([node])
            .attr("r", 1e-6)
            .transition()
            .attr("r", 4.5)
            .transition()
            .delay(1000)
            .attr("r", 1e-6)
            .remove();
        force.nodes().push(node); 
        force.start(); 
});

Here we create a new data point and add a circle with the x and y attributes of that data point. I go to the radius of the nodes and then delete () it. Here I do not follow a bit - BEFORE deleting it, the data point is added to the force.nodes () array, and not to the circle itself, namely to the data point. Then I run () the force.

  • Why do we delete the circle before pushing the data point into the force.nodes () array.
  • force.nodes(), ? - ?
  • () , ? , force() node?

UPDATE: , , , force() .

: . x y , . , x y , . - / x y, , .

?

+4
2

, , ... -, , -, .

-

		var w = 900, h = 400, nodes = [],
						indx = 0, show = false,

		svg = d3.select("body").append("svg")
		.attr("width", w)
		.attr("height", h),

		force = d3.layout.force()
		.nodes(nodes)
		.size([w, h])
		.gravity(0)
		.charge(1)
		.friction(0.7),

		outputDiv = d3.select("body").insert("div", "svg").attr("id", "output");

		$("#toggleShow").click(function (e) {
			d3.selectAll(".dead").attr("opacity", (show = !show) ? 0.2 : 0)
			$(this).text((show ? "don't " : "") + "show dead nodes")
		});
		$("#clear").click(function (e) {
			nodes.length = 0;
			d3.selectAll("circle").remove();
		});


		force.on("tick", function (e) {
			outputDiv.text("alpha:\t" + d3.format(".3f")(force.alpha())
				+ "\tnodes:\t" + force.nodes().length)
			var circles = svg.selectAll("circle").data(nodes, function (d) { return d.id })

			//ENTER
			//  direct
			//    data is there but the circle has been deleted by completion of transition
			//    replace the previously live node with a dead one
			//  idiomatic
			//    always zero size
			circles.enter().append("circle")
				.attr("r", 4.5)
				.attr("class", "dead")
			.attr("opacity", show ? 0.2 : 0);
			//UPDATE+ENTER
			circles
				.attr("cx", function (d) { return d.x; })
				.attr("cy", function (d) { return d.y; });
		});

		svg.on("mousemove", onMove)
		.on("touchmove", onMove)
		.on("touchstart", onMove);

		function onMove() {
		  d3.event.preventDefault();
		  d3.event.stopPropagation();
		  updateMethod.call(this)
		}

		function direct() {
			return function () {
			  var pointM = d3.mouse(this), pointT = d3.touches(this),
						point = pointT.length ? pointT[0] : pointM,
						node = { x: point[0], y: point[1], id: indx++ };

				svg.append("circle")
							.data([node])
									.attr("class", "alive")
									.attr("r", 1e-6)
									.transition()
									.attr("r", 4.5)
									.transition()
									.delay(1000)
									.attr("r", 1e-6)
									.remove();
				force.nodes().push(node);
				force.start();
			}
		} /*direct*/


		updateMethod = direct();
	body, html {
			width:100%;
			height:100%;
	}
		#vizcontainer {
			width: 100%;
			height: 100%;
		}

	 svg {
			outline: 1px solid red;
			width: 100%;
			height: 100%;
		}

		#output {
			pointer-events: none;  
			display: inline-block;
			z-index: 1;
			margin: 10px;
		}

		button {
			display: inline-block;
			margin: 10px;
		}
		.dead {
			fill: white;
			stroke: black;
			stroke-width: 1px;
		}
<button id="toggleShow" name="">show dead nodes</button>
	<button id="clear" name="clear">clear</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Hide result

, , nodes , , . , () : - .

...

  • ? ...
  • , . , .
  • , , force.nodes(), , , x y, d3.force, , . - , force.start(). force.start() , . , RTFC, , .

, d3...

    ;(function() {
      var w = 900, h = 400, nodes = [], touch,

          svg = d3.select("#vizcontainer").append("svg")
          .attr("width", w)
          .attr("height", h),

          force = d3.layout.force()
          .size([w, h])
          .gravity(0)
          .charge(1)
          .friction(0.7),

          outputDiv = d3.select("body").insert("div", "#vizcontainer").attr("id", "output").attr("class", "output"),
          touchesDiv = d3.select("body").insert("div", "#output").attr("id", "touches")
          .style("margin-right", "10px").attr("class", "output");


      force.on("tick", function (e) {

        outputDiv.text("alpha:\t" + d3.format(".3f")(force.alpha())
          + "\tnodes:\t" + force.nodes().length)

        svg.selectAll("circle")
        .attr("cx", function (d) { return d.x; })
        .attr("cy", function (d) { return d.y; });
      });

      svg.on("mousemove", onMove);
      svg.on("touchmove", onTouch);
      svg.on("touchstart", onTouch);

      function onMove() {
        updateMethod.call(this)
      }
      function onTouch() {
        d3.event.preventDefault();
        d3.event.stopPropagation();
        updateMethod.call(this)
      }

      function idiomatic() {
        force.nodes(nodes);
        return function () {
          var pointM = d3.mouse(this), pointT = d3.touches(this),
              point = pointT.length ? pointT[0] : pointM,
          node = { x: point[0], y: point[1] };

          //touchesDiv.text(pointT.length ? pointT : "mouse");

          nodes.push(node);

          svg.selectAll("circle")
          .data(nodes)
          .enter().append("circle")
          .attr("r", 1e-6)
          .transition("in")
          .attr("r", 4.5)
          .transition("out")
          .delay(1000)
          .attr("r", 1e-6)
          .remove()
          .each("end.out", (function (n) {
            return function (d, i) {
              //console.log("length: " + nodes.length + "\tdeleting " + i)
              var i = nodes.indexOf(n);
              nodes.splice(i, 1)
            }
          })(node));

          force.start();
        }
      } /*idiomatic*/


      updateMethod = idiomatic();
    })()
  body, html {
      width:100%;
      height:100%;
  }
    #vizcontainer {
      width: 100%;
      height: 100%;
    }

   svg {
      outline: 1px solid red;
      width: 100%;
      height: 100%;
    }

    .output {
      pointer-events: none;  
      display: inline-block;
      z-index: 1;
      margin: 10px;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
  <div id="vizcontainer"></div>
Hide result

. , , , . , , . end - . , node , .

, .

+2

: Remove() ( ). . .remove().

-: - , :

force.on("tick", function () {
    svg.selectAll("circle")
    .attr("cx", function (d) {return d.x;})
    .attr("cy", function (d) {return d.y;});
});

: .

0

All Articles