首先需要说的是,我对d3.js完全陌生(我使用的是版本4)。现在我有嵌套的节点对象,并尝试在单击父元素后绘制子元素。它部分工作:我可以绘制子节点,但不能绘制从父圆圈到子圆圈的链接。我有这个错误:
错误:遗失:哺乳动物
和
TypeError:无法创建属性' vx'在字符串'哺乳动物'
看起来source
已成功创建,但target
在第一个链接和其他链接处中断:
我不确定问题出在哪里,所以我创建了一个关于我现在拥有的所有代码的小提琴:https://jsfiddle.net/L6c6pxrv/4/
@KEKUATAN建议我将新数组分配给links
,不要推送每个项目。结果是:https://jsfiddle.net/L6c6pxrv/3/。没有任何错误,但看起来链接仍然不知道源和目标的坐标。
以下是我在圆圈点击后尝试实现的内容(此处我使用固体数组节点和链接从一开始就定义):https://jsfiddle.net/L6c6pxrv/2/
感谢您的帮助!
答案 0 :(得分:1)
问你是否需要解释我会尽力而为,但现在不能回家
像我说的那样在d3上的每个图表之前都有结构先了解它之前,了解这个结构图,如果你看到工作findle上的数据数组你会看到没有子对象和id或源2之间的数组有相同的价值。 我假设你的数据在2个数据数组,id和source之间没有相同的数据值,这就是为什么你有错误:遗失:哺乳动物
我将缺少的mamal添加到子对象
如果您控制节点和链接,您会发现此图表类型生成vx和vy
TypeError:无法创建属性' vx'在字符串'哺乳动物'
是一个链误差因为没有哺乳动物所以他们不能在id =哺乳动物上做vx和vy
<强>错误:强>
我不能做&#34; M&#34;节点中间的文字与其他节目一样跳舞。
注意:强>
d3.forceSimulation()和d3.forceLink()我认为这是创建这样的图表的核心,这就是他们生成cildren或vx和vy的原因
<强>提示:强>
确保链接数据和节点数据有一个相同的值,如id和source,这样你就可以得到连接,试着不要相信我这只是分享我知道的东西,不是我所知道的,尝试拥有更好的老师更好地理解
var nodes = [
{
id: "mammal",
label: "Mammals",
fill: 'orange',
color: '#333333',
children: [
{
id: "mammal",
label: "Dogs",
fill: 'yellow',
color: 'orangered'
},
{
id: "dog",
label: "Dogs",
fill: 'yellow',
color: 'orangered'
},
{
id: "cat",
label: "Cats",
fill: 'white',
color: 'blue'
},
{
id: "fox",
label: "Foxes",
fill: 'green',
color: 'black'
},
{
id: "elk",
label: "Elk",
fill: 'black',
color: 'orangered'
},
{
id: "insect",
label: "Insects",
fill: '#333333',
color: 'lightblue',
children: [
{
id: "pike",
label: "Pikes",
fill: 'white',
color: 'forestgreen'
}
]
},
{
id: "ant",
label: "Ants",
fill: 'violet',
color: 'white'
},
{
id: "bee",
label: "Bees",
fill: 'white',
color: 'purple'
},
{
id: "fish",
label: "Fish",
fill: 'darkblue',
color: 'white'
},
{
id: "carp",
label: "Carp",
fill: 'purple',
color: 'white'
}
]
}
];
var links = [
// { target: "mammal", source: "dog" },
// { target: "mammal", source: "cat" },
// { target: "mammal", source: "fox" },
// { target: "mammal", source: "elk" },
// { target: "mammal", source: "insect" },
// { target: "mammal", source: "ant" },
// { target: "mammal", source: "bee" },
// { target: "mammal", source: "fish" },
// { target: "mammal", source: "carp" }
// { target: "insect", source: "pike" }
];
var width = window.innerWidth;
var height = window.innerHeight;
var svg = d3.select('svg');
// Append rect and make it draggable
svg.append('rect').style('width', width * 2).style('height', height * 2).style('fill', 'transparent');
var dragcontainer = d3.drag()
.on("drag", function(d) {
d3.select(this).attr("transform", "translate(" + (d.x = d3.event.x) + "," + (d.y = d3.event.y) + ")");
});
var g = d3.select('svg').select("g").datum({x: 0, y: 0}).call(dragcontainer);
var groupWrapper = svg.append('g');
// Zoom
var zoom = d3.zoom()
.scaleExtent([-Infinity, 100])
.on('zoom', zoomFn);
function zoomFn() {
d3.select('svg').select('g')
.attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.transform.k + ')');
}
d3.select('svg').call(zoom);
// simulation setup with all forces
var linkForce = d3
.forceLink()
.id(function (link) { return link.id })
.strength(function (link) { return 0.3 });
var simulation = d3
.forceSimulation()
.force('link', linkForce)
.force('charge', d3.forceManyBody().strength(-5000))
.force('center', d3.forceCenter(width / 2, height / 2));
var dragDrop = d3.drag().on('start', function (node) {
node.fx = node.x;
node.fy = node.y;
}).on('drag', function (node) {
simulation.alphaTarget(0.7).restart();
node.fx = d3.event.x;
node.fy = d3.event.y;
}).on('end', function (node) {
if (!d3.event.active) {
simulation.alphaTarget(0);
}
node.fx = null;
node.fy = null;
});
var linkElements = groupWrapper.append("g")
.attr("class", "links")
/**
* comment below
*/
.selectAll("line")
.data(links)
.enter().append("line")
.attr("stroke-width", 1)
.attr("stroke", "rgba(50, 50, 50, 0.2)");
var nodeElementsWrapper = groupWrapper.append("g").attr('class', '1');
var nodeElementsGroup = nodeElementsWrapper
.attr("class", "nodes")
.selectAll("circle")
.data(nodes)
.enter().append("g")
.attr('class', 'item')
.on("click", function(d) {
console.log("on click", d);
draw();
});
var circleElements = nodeElementsGroup
.append("circle")
.attr("r", 100)
.attr("fill", function(item) {
return item.fill;
})
.attr("stroke", function(item) {
return item.color;
})
.attr("stroke-width", function(item) {
})
.call(dragDrop);
var textElements = d3.selectAll('g.item')
.each(function(item, i) {
d3.select(this)
.append('text')
.attr("font-size", 50)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "central")
.attr("fill", function () { return item.color })
.text(function () { return item.id[0].toUpperCase() })
});
// Draw children
function draw() {
var newLinks = [
{ target: "mammal", source: "dog" },
{ target: "mammal", source: "cat" },
{ target: "mammal", source: "fox" },
{ target: "mammal", source: "elk" },
{ target: "mammal", source: "insect" },
{ target: "mammal", source: "ant" },
{ target: "mammal", source: "bee" },
{ target: "mammal", source: "fish" },
{ target: "mammal", source: "carp" }
];
newLinks.forEach(function(item) {
links.push(item);
});
console.log('LINKS: ', links);
nodeElementsGroup = nodeElementsWrapper
.attr("class", "nodes")
.selectAll("circle")
.data(nodes[0].children)
.enter().append("g")
.attr('class', 'item')
.on("click", function(d) {
console.log("on click", d);
});
circleElements = nodeElementsGroup
.data(nodes[0].children)
.append("circle")
.attr("r", 100)
.attr("fill", function(item) {
return item.fill;
})
.attr("stroke", function(item) {
return item.color;
})
.attr("stroke-width", function(item) {
})
.call(dragDrop);
textElements = d3.selectAll('g.item')
.each(function(item, i) {
var t = d3.select(this).text()
if (t=='M'){
}else{
d3.select(this)
.append('text')
.attr("font-size", 50)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "central")
.attr("fill", function () { return item.color })
.text(function () {
var s = item.id[0].toUpperCase()
if (s!=='M'){
return s
}
}).call(dragDrop)
}
})
linkElements = d3.select('g.links')
.attr("class", "links")
.selectAll("line")
.data(links)
.enter().append("line")
.attr("class", "link")
.attr("stroke-width", 1)
.attr("stroke", "rgba(50, 50, 50, 0.2)");
// simulation
simulation.nodes(nodes[0].children).on('tick', function() {
d3.selectAll('circle')
.attr('cx', function (node) { return node.x })
.attr('cy', function (node) { return node.y });
d3.selectAll('text')
.attr('x', function (node) { return node.x })
.attr('y', function (node) { return node.y });
d3.selectAll('line.link')
.attr('x1', function (link) { return link.source.x })
.attr('y1', function (link) { return link.source.y })
.attr('x2', function (link) { return link.target.x })
.attr('y2', function (link) { return link.target.y })
});
// simulation.force("link").links(d3.selectAll('line.link')); // "links" instead of d3.selectAll('line.link')
}
// Simulation
simulation.nodes(nodes).on('tick', function() {
circleElements
.attr('cx', function (node) { return node.x })
.attr('cy', function (node) { return node.y });
d3.selectAll('text')
.attr('x', function (node) { return node.x })
.attr('y', function (node) { return node.y });
linkElements
.attr('x1', function (link) { return link.source.x })
.attr('y1', function (link) { return link.source.y })
.attr('x2', function (link) { return link.target.x })
.attr('y2', function (link) { return link.target.y })
});
simulation.force("link").links(links);
&#13;
html {
background-color: gray;
}
body {
position: relative;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
svg {
position: fixed;
top: 0;
width: auto;
height: auto;
min-width: 100%;
min-height: 100%;
background-color: gray;
}
circle {
cursor: pointer;
}
text {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
cursor: pointer;
}
line {
stroke: #fff;
stroke-width: 1.5;
}
&#13;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<svg></svg>
</body>
</html>
&#13;