block by Kcnarf 1596cfdd49de0cd92f07dec9afd4f4e2

strange dancing behaviour

Full Screen

This block helps me to understand the noise-link behaviour that seems to emerge from the force layout. This behaviour originaly comes from Fil‘s block: Urquhart Force Mesh Dance

Acknowledgments to:

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  canvas {
    margin: 1px;
    border-radius: 1000px;
    box-shadow: 2px 2px 6px grey;
    cursor: crosshair;
  }
</style>
<body>
<script src="https://d3js.org/d3.v4.js"></script>
<script>

  var cbw = 1, //canvas border width
      cm = 10, //canvas margin
      totalWidth = 500,
      totalHeight = 500,
      width = totalWidth-(cm+cbw)*2,
      height = totalHeight-(cm+cbw)*2,
      midWidth = width/2,
      midHeight = height/2,
      τ = 2 * Math.PI;
	var sampleRate = 3,
  		pointCount = 360/sampleRate;
  		initialRadius = height/2;

  var nodes = d3.range(pointCount).map(function(i) {
    var degree = sampleRate*i,
    		radian = degree*τ/360;
    return {
      x: midWidth+initialRadius*Math.cos(radian),
      y: midHeight+initialRadius*Math.sin(radian),
      color: d3.hsl(degree, 1, 0.5)
    };
  });

  var links = nodes.slice(1).map( function (n,i) {
    return {
      source: nodes[i],
      target: n
    }
  });

  var force = d3.forceSimulation()
      .nodes(nodes.slice())
      .force("charge", d3.forceManyBody().strength(-25))
      .force("x", d3.forceX())
      .force("y", d3.forceY())
      .force("dance", function(alpha) {
        var m = 50*alpha;
          for(var i=1; i < nodes.length; i++) {
          var d = Math.sqrt((nodes[i-1].x - nodes[i].x)*(nodes[i-1].x - nodes[i].x) + (nodes[i-1].y - nodes[i].y)*(nodes[i-1].y - nodes[i].y));
           nodes[i].vx += m*(nodes[i-1].x - nodes[i].x)/d;
           nodes[i].vy += m*(nodes[i-1].y - nodes[i].y)/d;
        }
			})
      .force("center", d3.forceCenter(width / 2, height / 2))
      .on("tick", ticked);

  var canvas = d3.select("body").append("canvas")
      .attr("width", width)
      .attr("height", height)
      .on("ontouchstart" in document ? "touchmove" : "mousemove", moved);

  var context = canvas.node().getContext("2d");

  function moved() {
    var p1 = d3.mouse(this);
    nodes[0].fx = p1[0];
    nodes[0].fy = p1[1];
    force.alpha(0.1).restart();
  }

  function ticked() {
    context.lineWidth = 1;
    context.strokeStyle = "#bbb";
		
    context.clearRect(0, 0, width, height);
    
    //begin: draw segments
    context.beginPath();
    context.moveTo(links[0].source.x, links[0].source.y);
    for (var i = 1, n = links.length; i < n; ++i) {
      var link = links[i];
      context.lineTo(link.target.x, link.target.y);
    }
    context.stroke();
    //end: draw segments
		
    //begin: draw points
    for (var i = 0, n = nodes.length; i < n; ++i) {
      var node = nodes[i];
      context.beginPath();
      context.moveTo(node.x, node.y);
      context.arc(node.x, node.y, 1.5, 0, τ);
      context.fillStyle = node.color;
      context.stroke();
      context.fill();
    }
    //end: draw points

  }

</script>