title: Force simulation of texts on bubble-chart does not work
body: <p>I have a script in which I make circles and then append text to them. I want to use force simulation so that texts of different circles don't overlap. </p>
  
  <p>The issue that I am currently facing is shown in graph below: (2 red circles on the left have overlapping text)<a href="https://i.stack.imgur.com/55yIK.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/55yIK.png" alt="enter image description here"></a></p>
  
  <p>I used force simuation in my script for texts but nothing happens. I am not getting any error but still the texts are overlapping.  I have tried many solution but nothing seems to work. </p>
  
  <p>Following is my script:</p>
  
  <pre><code> function graph(data){
      //var margin = {top: 30, right: 20, bottom: 30, left: 50}
  
      var margin = 40,
      width = 600,
      height = 400;
  
      //   var force = d3.layout.force()
          // .nodes(datas)
          // .size([width, height]);
  
      simulation = d3.forceSimulation()
          .force("x", d3.forceX())
          .force("y", d3.forceY())
          .force("collide", d3.forceCollide(20)); 
  
      var xscale = d3.scaleLinear()
          .domain([0, d3.max(data, function (d) {
              return +d.student_percentile;
          })])
          .nice() 
          .range([0, width]);
  
      var yscale = d3.scaleLinear()
              .domain([0, d3.max(data, function (d) {
                  return +d.rank;
              })])
              .nice()
              .range([height, 0]);
  
      var xAxis = d3.axisBottom().scale(xscale).tickFormat(function(d) {
          return d &gt; 100 ? "Not Available" : d
      });
  
      var yAxis = d3.axisLeft().scale(yscale);
  
      var svg = d3.select('.chart')
          .classed("svg-container", true)
          .append('svg')
          .attr('class', 'chart')
          .attr("viewBox", "0 0 680 490")
          .attr("preserveAspectRatio", "xMinYMin meet")
          .classed("svg-content-responsive", true)
          .append("g")
          .attr("transform", "translate(" + margin + "," + margin + ")");
  
      svg.append("g")
          .attr("class", "y axis")
          .call(yAxis);
  
      svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);
  
      var color = d3.scaleOrdinal(d3.schemeCategory10);
  
      var local = d3.local();
      circles = svg.selectAll(null)
            .data(data)
            .enter()
            .append("circle")
            .attr("cx", width / 2)
            .attr("cy", height / 2)
            .attr("opacity", 0.3)
            .attr("r", 20)
            .style("fill", function(d){
              if(+d.admit_probability &lt;= 40){
                  return "red";
              }
              else if(+d.admit_probability &gt; 40 &amp;&amp; +d.admit_probability &lt;= 75){
                  return "yellow";
              }
              else{
                  return "green";
              }
            })
            .attr("cx", function(d) {
              return xscale(+d.student_percentile);
            })
            .attr("cy", function(d) {
              return yscale(+d.rank);
            })
            .on('mouseover', function(d, i) {
              local.set(this, d3.select(this).style("fill"));
              d3.select(this)
                .transition()
                .duration(1000)
                .ease(d3.easeBounce)
                .attr("r", 32)
                .style("cursor", "pointer")
                .attr("text-anchor", "middle");
                var d = this.__data__;
                show_details(d);
              }
             )
            .on('mouseout', function(d, i) {
              d3.select(this).style("fill", local.get(this));
              d3.select(this).transition()
                .style("opacity", 0.3)
                .attr("r", 20)
                .style("cursor", "default")
              .transition()
              .duration(1000)
              .ease(d3.easeBounce);
              remove_details();
            });
  
      texts = svg.selectAll(null)
        .data(data)
        .enter()
        .append('text')
        .attr("text-anchor", "middle")
        .text(function(d) {
          return d.abbreviation;
        })
        .attr("pointer-events", "none")
        .attr("font-family", "sans-serif")
        .attr("font-size", "12px")
        .attr("fill", "black");
  
    simulation.nodes(data).on("tick", function(){
          texts.attr("x", function(d) {
               return xscale(+d.student_percentile);
             })
               .attr("y", function(d) {
               return yscale(+d.rank);
             });
      });
  
  
    //        force.on("tick", function() {
  
    //   texts.attr("x", function(d) { return +d.student_percentile; })
    //       .attr("y", function(d) { return +d.rank; });
  
    // });
  
  
      svg.append("text")
          .attr("transform", "translate(" + (width / 2) + " ," + (height + margin) + ")")
          .style("text-anchor", "middle")
          .text("Percentile");
  
      svg.append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 0 - margin)
          .attr("x",0 - (height / 2))
          .attr("dy", "1em")
          .style("text-anchor", "middle")
          .text("Rank");
  
      $('circle').tipsy({ 
          gravity: 'w', 
          html: true, 
          title: function() {
              var d = this.__data__;
              return d.name + '&lt;br/&gt; Rank: ' + d.rank + '&lt;br/&gt; Admit Probaility: ' + d.admit_probability + '%'; 
          }
      });
  }
  </code></pre>
  
  <p>I even tried doing: </p>
  
  <pre><code> simulation.nodes(data).on("tick", function(){
          texts.attr("x", d3.forceX().x(function(d) {
               return xscale(+d.student_percentile);
             }))
               .attr("y", d3.forceY().y(function(d) {
               return yscale(+d.rank);
             }));
      });
  </code></pre>
  
  <p>This also does not work.</p>