2016-08-18 3 views
0

d3.jsマルチ焦点の力で衝突し、私がやろうとしていることは、この近くにある:私は理解していない何http://codepen.io/fabiobiondi/pen/nFxyDハンドルは、私がd3.jsとの新たなんだレイアウト

// GROUPS: 0 Web | 1: Adobe | 2: hybrid 
var data = [ 
    {"id": 0, "name": "AngularJS", "r": 50 }, 
    {"id": 0, "name": "HTML5", "r": 40 }, 
    {"id": 0, "name": "Javascript", "r": 30 }, 
    {"id": 0, "name": "NodeJs", "r": 30 }, 
    {"id": 0, "name": "D3.js", "r": 40 }, 
    {"id": 0, "name": "CreateJS", "r": 45 }, 
    {"id": 0, "name": "Cordova", "r": 40 }, 
    {"id": 0, "name": "CSS", "r": 40 }, 
    {"id": 0, "name": "SVG", "r": 20 }, 
    {"id": 0, "name": "PHP", "r": 20 }, 
    {"id": 0, "name": "jQuery", "r": 30 }, 

    {"id": 1, "name": "Actionscript", "r": 50 }, 
    {"id": 1, "name": "Flash", "r": 32 }, 
    {"id": 1, "name": "Flex", "r": 50 }, 
    {"id": 1, "name": "AIR", "r": 40 }, 
    {"id": 1, "name": "Photoshop", "r": 30 }, 
    {"id": 1, "name": "Illustrator", "r": 30 }, 

    {"id": 2, "name": "Node Webkit", "r": 40 }, 
    {"id": 2, "name": "Chrome App", "r": 30 }, 
    {"id": 2, "name": "Cordova", "r": 45 }, 
]; 

var width = window.innerWidth, 
    height = 450; 

var fill = d3.scale.category10(); 

var nodes = [], labels = [], 
    foci = [{x: 0, y: 150}, {x: 350, y: 150}, {x: 200, y: 150}]; 

var svg = d3.select("body").append("svg") 
    .attr("width", "100%") 
    .attr("height", height) 
    //.attr("domflag", ''); 

var force = d3.layout.force() 
    .nodes(nodes) 
    .links([]) 
    .charge(-400) 
    //.chargeDistance(200) 
    .gravity(0.1) 
    .friction(0.8) 
    .size([width, height]) 
    .on("tick", tick); 

//var node = svg.selectAll("circle"); 
var node = svg.selectAll("g"); 

var counter = 0; 

function tick(e) { 
    var k = .1 * e.alpha; 

    // Push nodes toward their designated focus. 
    nodes.forEach(function(o, i) { 
    o.y += (foci[o.id].y - o.y) * k; 
    o.x += (foci[o.id].x - o.x) * k; 
    }); 

    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 

} 


var timer = setInterval(function(){ 

    if (nodes.length > data.length-1) { clearInterval(timer); return;} 

    var item = data[counter]; 
    nodes.push({id: item.id, r: item.r, name: item.name}); 
    force.start(); 

    node = node.data(nodes); 

    var n = node.enter().append("g") 
     .attr("class", "node") 
     .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) 
     .style('cursor', 'pointer') 
     .on('mousedown', function() { 
     var sel = d3.select(this); 
     sel.moveToFront(); 
     }) 
     .call(force.drag); 

    n.append("circle") 
     .attr("r", function(d) { return d.r; }) 
     .style("fill", function(d) { return fill(d.id); }) 

    n.append("text") 
     .text(function(d){ 
      return d.name; 
     }) 
     .style("font-size", function(d) { 
      return Math.min(2 * d.r, (2 * d.r - 8)/this.getComputedTextLength() * 16) + "px"; 
     }) 
     .attr("dy", ".35em") 

    counter++; 
}, 100); 


d3.selection.prototype.moveToFront = function() { 
    return this.each(function(){ 
    this.parentNode.appendChild(this); 
    }); 
}; 

function resize() { 
    width = window.innerWidth; 
    force.size([width, height]); 
    force.start(); 
} 

d3.select(window).on('resize', resize); 

ですどのようにしてサークルが衝突するかどうかを制御できます。

私はこのような衝突機能を試しましたが、https://bl.ocks.org/mbostock/1804919は動作しません。パディング値を変更すると、サークルは自分自身を回避し続けます。私が望むのは、内部のテキストが隠されていないことを確かめるために、衝突を許可することですが、それほど多くはありません(10pxとしましょう)。

答えて

1

私はこの例を実装している:https://bl.ocks.org/mbostock/7881887

私はコリジョン機能を追加しました:

// Resolves collisions between d and all other circles. 
function collide(alpha) { 
    var quadtree = d3.geom.quadtree(nodes); 
    return function(d) { 
    //console.log(d) 
    var r = d.r + maxRadius + Math.max(padding, clusterPadding), 
     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.r + quad.point.r + (d.cluster === quad.point.cluster ? padding : clusterPadding); 
     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; 
    }); 
    }; 
} 

これはすべてのように、私は文句を言わない、ここで説明する必要が上記のリンクで説明されています。例では

そのd.radiusいますが、私はこのように働いd.r.Also maxRadius持っている:上記

var maxRadius = data.reduce(function(sum, d){ 
    return Math.max(sum,d.r) 
}, 0); //get maximum radius 

は、データ配列を低減し、R(半径)の最大値を取得します。彼らは私が作った唯一の変化です。

そして私はあなたのダニ機能を更新しました:

function tick(e) { 
    var k = .1 * e.alpha; 

    // Push nodes toward their designated focus. 
    nodes.forEach(function(o, i) { 
    // console.log(o) 
    o.y += (foci[o.id].y - o.y) * k; 
    o.x += (foci[o.id].x - o.x) * k; 
    }); 

    node 
    .each(collide(.5)) //call collide function here 
    .attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }) 
    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 

} 

これは、あなたが持っていたマルチ焦点と衝突検出の世話をします。

更新フィドル:https://jsfiddle.net/thatOneGuy/392kwuru/

+0

私はフィドルすべての時間を使用して、私はそれに行った理由youreの不思議だけであれば、codepenのレイアウトを好まない:)希望 – thatOneGuy

+0

はどうもありがとう助け、私が言うことができません私は今まで理解していましたが、負の値をパディングにすると、私が望むものが得られます。私はこの他の例を勉強していました:https://bl.ocks.org/mbostock/2990a882e007f8384b04827617752738、それはv4でやるのが簡単な方法ではありませんか? – sam

関連する問題