[英]d3 update tree layout with dynamic data
用d3樹形布局更新模型的最簡單方法是什么。
這是示例http://jsfiddle.net/mnk/vfro9tkz/
var data = {
name: 'Music',
children: [{
name: 'Rock',
children: [{
name: 'Two'
}, {
name: 'Three',
children: [{
name: 'A'
}, {
name: 'Bonjourallo'
}, {
name: 'Coco coco coco coco'
}]
}, {
name: 'Four'
}]
}, {
name: 'Rap',
children: [{
name: 'Hip-Hop/Rap'
}]
}]
};
var svg = d3.select('body').append('svg');
svg.attr('width', 700)
.attr('height', 400);
var tree = d3.layout.tree().size([600, 300]);
function update(model) {
var nodes = tree.nodes(model);
var links = tree.links(nodes);
nodes.forEach(function(d, i) {
d.index = d.parent ? d.parent.children.indexOf(d) : 0;
d.width = getNameLength(d.name);
if (!hasNephewOrChildren(d)) {
d.x = getHorizontalPosition(d)
d.y = (d.parent ? d.parent.y : 0) + 40;
d.mode = 'horizontal';
} else {
d.x = d.depth * 60;
d.y = getVerticalPosition(d);
d.mode = 'vertical';
}
});
var node = svg.selectAll('.node')
.data(nodes)
.enter()
.append('g').attr('class', 'node')
.attr('opacity', 1)
.attr('visibility', function(d) {
return d.depth ? 'visible' : 'hidden'
})
.attr('transform', function(d, i) {
return 'translate(' + d.x + ',' + d.y + ')'
});
var lineFunction = d3.svg.line()
.x(function(d) {
return d.x;
})
.y(function(d) {
return d.y;
})
.interpolate("linear");
var paths = svg.selectAll('g.node').append("path")
.attr("d", function(d) {
return lineFunction(generatePath(d));
})
.attr("stroke", "#aaa")
.attr("stroke-width", 1)
.attr("fill", "none");
function generatePath(d) {
var points = [];
if (d.depth > 1) {
if (d.mode === 'horizontal') {
points.push({
x: d.parent.x - d.x + d.parent.width,
y: -25
});
points.push({
x: d.width / 2,
y: -25
});
points.push({
x: d.width / 2,
y: 0
});
} else {
points.push({
x: d.parent.x - d.x + d.parent.width / 2,
y: d.parent.y - d.y + 30
});
points.push({
x: d.parent.x - d.x + d.parent.width / 2,
y: 15
});
points.push({
x: d.parent.x - d.x + d.parent.width / 2 + 15,
y: 15
});
}
}
return points;
}
node.append('rect')
.attr('class', 'rect')
.attr('width', function(d, i) {
return d.width
})
.attr('height', 30)
.attr('rx', 15)
node.append('text')
.text(function(d) {
return d.name
})
.attr('x', 10)
.attr('y', 20);
var close = node.append('g')
.attr('class', 'remove-icon-group')
.on('click', function(d) {
console.log('todo remove d and all childrens.');
// update(model);
})
.attr('transform', function(d, i) {
return 'translate(' + (d.width - 15) + ',15)'
});
close.append('circle')
.attr('class', 'remove-icon')
.attr('r', 10)
close.append('line')
.attr('x1', -4)
.attr('x2', 4)
.attr('y1', -4)
.attr('y2', 4)
.attr('stroke', '#a0a0a0')
.attr('stroke-width', 1);
close.append('line')
.attr('x1', 4)
.attr('x2', -4)
.attr('y1', -4)
.attr('y2', 4)
.attr('stroke', '#a0a0a0')
.attr('stroke-width', 1);
}
update(data);
function getLastDescendant(d) {
if (d.children && d.children.length) {
return getLastDescendant(d.children[d.children.length - 1]);
}
return d;
}
function hasNephewOrChildren(d) {
var siblings = d.parent ? d.parent.children : [d];
var hasChildren = false;
siblings.forEach(function(sibling) {
if (sibling.children && sibling.children.length) {
hasChildren = true;
}
});
return hasChildren;
}
function getHorizontalPosition(d) {
if (d.index === 0) {
return d.parent ? d.parent.x + 60 : 0;
}
var prevSibling = d.parent.children[d.index - 1];
return prevSibling.x + prevSibling.width + 10;
}
function getVerticalPosition(d) {
var prevY = (d.parent ? d.parent.y : -40);
if (d.index) {
var prevSibling = d.parent.children[d.index - 1];
var lastDescendant = getLastDescendant(prevSibling);
prevY = lastDescendant.y;
}
return prevY + 40;
}
function getNameLength(str) {
var length = str.length * 8;
return length < 60 ? 60 + 30 : length + 30;
}
你很親密 您已經提取了所有繪制代碼以進行update
,並且在某個地方已注釋掉需要再次調用它。 您需要弄清楚如何響應用戶單擊來修改模型,然后使用新模型調用update
。
您將遇到的事情是,當您再次調用update
時,某些DOM節點將已經出現在屏幕上。 也就是說,輸入選擇將為空,但更新選擇將不會為空。 處理此問題的最簡單,最丑陋的方法是刪除並重新添加所有節點:
svg.selectAll('.node').remove();
svg.selectAll('.node')
.data(nodes)
.enter()
.append("g") // and so on
常規更新模式中介紹了執行此操作的更好方法(請確保同時查看所有三個方法)。 您還應該閱讀.enter()docs的最后一段。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.