2015-10-19 3 views
3

Я работаю с D3 для создания иерархической модели некоторых данных.Поворот D3 SVG для выравнивания до определенного угла

enter image description here

То, что я хочу быть в состоянии сделать, это нажать на краевой узел и он выстраиваться с красной линией.

enter image description here

То, что я пытался до сих пор пытаюсь вычислить разницу угла между (х, у) расположения в центре, и (х, у) местоположения краевого узла. Это не дало мне правильных результатов.

Я думаю, что правильный путь к этому, чтобы получить угол узла (по отношению к середине). Хотя у меня много неприятностей, так как я не могу найти, какое свойство хранит эту информацию. Иерархия края базируется этот:

http://bl.ocks.org/mbostock/7607999

текст генерируется с помощью следующего фрагмента кода:

node = node 
     .data(nodes.filter(function(n) { return !n.children; })) 
    .enter().append("text") 
     .attr("class", "node") 
     .attr("dy", ".31em") 
     .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); }) 
     .style("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) 
     .text(function(d) { return d.key; }) 
     .on("mouseover", mouseovered) 
     .on("mouseout", mouseouted); 

Любая информация будет очень полезна. Благодаря

ответ

2

Линия заботится о вращении колеса всего следующий:

.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); }) 

Данные совмещен с красной линией, когда d.x = 270. В вашем случае, вызывая «происхождение» выбранный фрагмент данных (тот, который должен находиться на красной линии), вам нужно дать угол dx - origin.x + 270.

Чтобы сохранить значения между 0 и 360, следующий трюк работает:

(d.x - origin.x + 270 +360) % 360 

Так самый простой способ, на мой взгляд, чтобы добавить поле «угол» в ваших данных, а затем использовать его вместо йх

node = node 
     .data(nodes.filter(function(n) { return !n.children; })) 
    .enter().append("text") 
     .attr("class", "node") 
     .attr("dy", ".31em") 
     .each(function(d) { d.angle = (d.x - origin.x + 270 +360) % 360 }) 
     .attr("transform", function(d) { return "rotate(" + d.angle - 90 + ")translate(" + (d.y + 8) + ",0)" + (d.angle < 180 ? "" : "rotate(180)"); }) 
     .style("text-anchor", function(d) { return d.angle < 180 ? "start" : "end"; }) 
     .text(function(d) { return d.key; }) 
     .on("mouseover", mouseovered) 
     .on("mouseout", mouseouted); 
1

Я думаю, что правильный путь к этому, чтобы получить угол узла (по отношению к центру)

У вас уже есть угол узла, может быть, это было путают, так как вы назначаете поворот дважды. Но это может быть объединено в один, выполнив следующие действия:

.attr("transform", function(d) { 
    var r = d.x < 180 ? d.x - 90 : (d.x - 90) + 180; 
    return "rotate(" + r + ")translate(" + (d.y + 8) + ",0)"; 
}) 

r будет углом, но есть потенциальные «проблемы» (или просто делает код анимации немного более громоздкий) с этой версией, потому что некоторые r значения будут отрицательными.

Лучший подход, чтобы избежать перевода Y-оси, а не оси X, как вы сейчас делаете.

.attr("transform", function(d) { 
    // Simpler version for assigning the r value and avoid negatives. 
    var r = d.x > 180 ? d.x + 180 : d.x; 
    // Notice the negative value for the Y Axis. 
    return "rotate(" + r + ")translate(0, -" + (d.y + 8) + ")"; 
}) 

Теперь у вас есть углы узлов по отношению к центру, как вы хотели.

Дополнительное примечание, которое поможет вам понять, как его выровнять. Ваша красная линия находится под углом .Таким образом, чтобы повернуть графику, нужно найти разницу между r и 180.

Смежные вопросы