這裏是一個遞歸函數照顧重排:
function makeRoot(source) {
if (!source.parent) return; //nothing to do if source is already root
makeRoot(source.parent); //flip the higher branches recursively so that the parent becomes root of the tree
var index = source.parent.children.indexOf(source);
source.parent.children.splice(index, 1); //corrected here: you need to remove the right element from the children list
source.parent.parent = source;
source.children.push(source.parent);
delete source.parent; //added: now that the original parent is linked, make source the root of the tree
}
我不知道如何強制原始節點的孩子被吸引到南部和在北邊休息。首先要做的事情是到知道每個節點必須在哪一邊(這很容易:默認情況下所有節點都是「北」的),然後在撥打makeRoot
之前訪問source
的子樹,並告訴它們是「南」)。但之後,我對d3的樹佈局不夠熟悉,無法執行「北/南」約束。
更新爲南北走向,你可以嘗試以下方法:
- 保持指針
oldParent=source.parent
到所選擇的節點
- 一旦佈局完成後的原始父,在更新svg之前,計算
offsetX= 90- oldParent.x
(父位置和北軸之間的差異 - 注意:我不確定北軸是90°,但它應該是0,90,180或270中的一個。只是嘗試所有;))
轉變周圍的所有節點通過offsetX
量(保持在0和359之間的夾角):
nodes.forEach(function(d) {
d.x = (d.x + offsetX) % 360;
});
,那麼你可以更新SVG:整個樹應當使原來的母公司點北旋轉。 ..這應該足以獲得你想要的視覺效果。
更新#2另一種方法,使南北排列。
見小提琴這裏:https://jsfiddle.net/qo4w0ktn/4/
的想法是計算最左邊和最右邊,最葉片的角度,原來的兒童中,並旋轉整個圖,直到平均南這兩個角度點。這意味着您需要跟蹤樹中的「原始」孩子,這是通過我的d.real_children
屬性完成的。功能leftmostLeaf
和rightmostLeaf
很簡單(請參閱小提琴)。
function rotateSouth(source, nodes) {
var lx = leftmostLeaf(source);
var rx = rightmostLeaf(source);
if (lx>rx) rx += 360; //this happens if the interval overlap angle 0
var offsetX= 180- (lx+rx)/2; //the median point (=(lx+rx)/2) should be pushed south (=180)
nodes.forEach(function(d) {
d.x = (d.x + offsetX) % 360; //rotate every node by the same offset
});
}
您嘗試過的方法很好,它必定是您的函數中的一個問題。你能分享你試過的功能的代碼嗎? – tarulen
我已經添加了我在帖子中提到的代碼。 –
你想只在樹中選擇節點的父節點,還是隻有父節點等,直到原始根節點? – tarulen