气泡图中的工具提示定位

时间:2015-11-18 05:28:32

标签: extjs d3.js tooltip bubble-chart

我创建了一个d3.js气泡图。 我希望工具提示始终位于圆圈边框的右上角,无论光标在圆圈内移动的位置。

这就是我创建工具提示的方式。

        new Ext.ToolTip({
        title: desc,
        radius:circle[0][i].__data__.radius,
        anchor: 'left',
        autoHide: false,
        showDelay:0,
        trackMouse: false,
        anchorToTarget: false,
        ttype:"ltype"+i,
        target: circle[0][i],
        listeners:{
             move:function(a,b,c){
                  var currentType = this.ttype;
                 items.push(this);
                 for(var i=0;i<items.length;i++){
                     if(items[i].ttype!=currentType){
                         if(items[i].isVisible()){
                           items[i].hide();   
                         }
                     }
                 }

                }
        }

    });

我该怎么办? 这是我的fiddle

1 个答案:

答案 0 :(得分:1)

如果您使用鼠标悬停事件,则有可能的解决方案。

&#13;
&#13;
var data = {
  name: "layout",
  children: [{
    name: "AxisLayout",
    size: 6725
  }, {
    name: "BundledEdgeRouter",
    size: 3727
  }, {
    name: "CircleLayout",
    size: 9317
  }, {
    name: "CirclePackingLayout",
    "size": 12003
  }, {
    name: "DendrogramLayout",
    "size": 4853
  }, {
    name: "ForceDirectedLayout",
    "size": 8411
  }, {
    name: "IcicleTreeLayout",
    "size": 4864
  }, {
    name: "IndentedTreeLayout",
    "size": 3174
  }, {
    name: "Layout",
    "size": 7881
  }, {
    name: "NodeLinkTreeLayout",
    "size": 12870
  }, {
    name: "PieLayout",
    "size": 2728
  }, {
    name: "RadialTreeLayout",
    "size": 12348
  }, {
    name: "RandomLayout",
    "size": 870
  }, {
    name: "StackedAreaLayout",
    "size": 9121
  }, {
    name: "TreeMapLayout",
    "size": 9191
  }]
};

var margin = {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  },
  width = 400 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

var n = data.children.length,
  m = 1,
  padding = 6,
  radius = d3.scale.sqrt().range([0, 12]),
  color = d3.scale.category10().domain(d3.range(m)),
  x = d3.scale.ordinal().domain(d3.range(m)).rangePoints([0, width], 1);

var nodes = d3.range(n).map(function() {
  var i = Math.floor(Math.random() * m), //color
    v = (i + 1) / m * -Math.log(Math.random()); //value
  return {
    radius: radius(v),
    color: color(i),
    cx: x(i),
    cy: height / 2,
  };

});

nodes.forEach(function(item, index) {
  item.radius = data.children[index].size / 300;
});

var force = d3.layout.force()
  .nodes(nodes)
  .size([width, height])
  .gravity(0)
  .charge(0)
  .on("tick", tick)
  .start();

var drag = force.drag()
  .on("drag", dragmove);

function dragmove(d) {
  var euclideanDistance = Math.sqrt(Math.pow((d.px - 198), 2) + Math.pow((d.py - 198), 2));

  if (euclideanDistance > 198 - d.radius) {
    d.px = d.px - 198;
    d.py = d.py - 198;

    var radians = Math.atan2(d.py, d.px);

    d.px = Math.cos(radians) * (198 - d.radius) + 198;
    d.py = Math.sin(radians) * (198 - d.radius) + 198;
  }
}

var svg = d3.select("#chart").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var circle = svg.selectAll("circle")
  .data(nodes)
  .enter().append("circle")
  .attr("r", function(d) {
    return d.radius;
  })
  .style("fill", function(d, i) {
    return "green";
  })
  .call(drag);

var tip = Ext.create('Ext.tip.ToolTip', {
  title: 'test',
  width: 150,
  height: 40,
  radius: 5,
  hidden: true,
  anchor: 'left',
  autoHide: false,
  trackMouse: true,
  anchorToTarget: false
});

circle.on('mouseover', function(d, i) {
  tip.setTitle("radius: " + d.radius);
  tip.showAt([d.x - d.radius, d.y - d.radius]);
});

function tick(e) {
  circle.each(gravity(.2 * e.alpha))
    .each(collide(.5))
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    });
}

// Move nodes toward cluster focus.
function gravity(alpha) {
  return function(d) {
    d.y += (d.cy - d.y) * alpha;
    d.x += (d.cx - d.x) * alpha;
  };
}

// Resolve collisions between nodes.
function collide(alpha) {
  var quadtree = d3.geom.quadtree(nodes);
  return function(d) {
    var r = d.radius + radius.domain()[1] + padding,
      nx1 = d.x - r,
      nx2 = d.x + r,
      ny1 = d.y - r,
      ny2 = d.y + r;
    quadtree.visit(function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== d)) {
        var x = d.x - quad.point.x,
          y = d.y - quad.point.y,
          l = Math.sqrt(x * x + y * y),
          r = d.radius + quad.point.radius + (d.color !== quad.point.color) * padding;
        if (l < r) {
          l = (l - r) / l * alpha;
          d.x -= x *= l;
          d.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
}
&#13;
svg {
  /*border: 1px solid black;*/
  border-radius: 50%;
  background: lightgray;
}
circle {
  stroke: #fff;
} 
&#13;
<link href="http://dev.sencha.com/deploy/ext-4.1.0-gpl/resources/css/ext-all.css" rel="stylesheet"/>
<script src="http://cdn.sencha.com/ext/gpl/4.1.1/ext-all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<p id='chart'>
&#13;
&#13;
&#13;