d3 工具提示。可折叠的树。调用 .on(mouseover,function(....)) 时出错
d3 tooltip. Collapsible tree. Error when .on(mouseover,function(....)) is called
我正在尝试将工具提示添加到可折叠树中,但我遇到了问题。错误似乎发生在这段代码中,如下所示(我将附上完整的代码片段以及用于调试目的)
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("circle")
.attr('r',function(d) { return d.size; })
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; })
.attr('cursor', 'pointer')
.on("mouseover", mouseover)
.on("mousemove", function(d){mousemove(d);})
.on("mouseout", mouseout);
错误消息:未捕获类型错误:nodeUpdate.select(...).attr(...).style(...).attr(.. .).on 不是函数
.on 函数未被识别为函数。我相信这与 t运行 节点的位置有关,但我不确定如何解决这个问题。
<!DOCTYPE html>
<meta charset="utf-8">
<style>
div.container {
width: 100%;
}
header {
height: 35px;
padding: 1em;
color: white;
background-color: gray;
clear: left;
text-align: center;
justify-content: center;
font-family: Calibri;
font-size: 35px;
font-weight: bold;
}
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 13px sans-serif;
}
.link {
fill: none;
stroke-opacity: 0.4;
stroke: purple;
stroke-width: 3.5px;
}
#content img {
position: absolute;
bottom: 0px;
right: 0px;
}
h2 {
font-family: Calibri;
font-size: 35px;
font-weight: bold;
text-align: center;
}
div.container1 span {
top: 50%;
justify-content: center;
text-align: center;
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
}
</style>
<body bgcolor='#F8F9F9'>
<script src="https://d3js.org/d3.v3.min.js"></script>
<div class="container">
<table>
<tr>
<td width="90%">
<div id="hier" align="left">
<tr>
<script>
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 1500 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var flare = {
"name": "AON",
"size": 4,
"children": [{
"name": "India",
"size": 4,
"children": [{
"name": "ARS",
"size": 4,
"children": [
{
"name": "hhh",
"size": 4
},
{
"name": "AAA",
"size": 4
},
{
"name": "BBB",
"size": 4
},
{
"name": "cCC",
"size": 8
},
{
"name": "ddd",
"size": 4
},
{
"name": "eee",
"size": 4
},
{
"name": "fff",
"size": 4
},
{
"name": "ggg",
"size": 4
},
{
"name": "hhh",
"size": 4
},
{
"name": "www",
"size": 4
},
{
"name": "qwww",
"size": 8
},
{
"name": "sd",
"size": 4
},
{
"name": "tere",
"size": 4
},
{
"name": "rtr",
"size": 4
},
{
"name": "wqw",
"size": 4
},
{
"name": "hrfg",
"size": 4
}
]
}]
},
{
"name": "Singapore",
"size": 4,
"children": [{
"name": "H&B",
"size": 4,
"children": [{
"name": "aasd",
"size": 4
},
{
"name": "sdw",
"size": 4
},
{
"name": "ghrr",
"size": 4
},
{
"name": "tyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "eds",
"size": 4
},
{
"name": "hrtr",
"size": 8
},
{
"name": "wew",
"size": 4
},
{
"name": "uyt",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "yrt",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "erewr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "kyjy",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "wew",
"size": 4
},
{
"name": "sdsf",
"size": 4
},
{
"name": "wewt",
"size": 4
},
{
"name": "wetdse",
"size": 4
},
{
"name": "wetw",
"size": 4
},
{
"name": "qwsd",
"size": 4
},
{
"name": "yrytw",
"size": 4
},
{
"name": "wewax",
"size": 4
},
{
"name": "jttut",
"size": 4
},
{
"name": "scscw",
"size": 4
},
{
"name": "wetvd",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "zc",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "zerete",
"size": 8
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "yeer",
"size": 4
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "wewretre",
"size": 4
},
{
"name": "ssdsrere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
}
]
}
]
},
{
"name": "US",
"size": 4,
"children": [{
"name": "Benfield",
"size": 4,
"children": [{
"name": "wes",
"size": 4
},
{
"name": "sd",
"size": 4
},
{
"name": "dds",
"size": 4
},
{
"name": "sdsd",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "ryr",
"size": 4
},
{
"name": "ty",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "ggrt",
"size": 4
},
{
"name": "wetyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hrfg",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hhf",
"size": 8
},
{
"name": "ere",
"size": 4
},
{
"name": "vfgd",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "xx",
"size": 4
},
{
"name": "wqwq",
"size": 4
},
{
"name": "xasa",
"size": 4
},
{
"name": "ooo",
"size": 4
},
{
"name": "ppp",
"size": 4
},
{
"name": "ll",
"size": 4
},
{
"name": "lljk",
"size": 4
},
{
"name": "kjjk",
"size": 4
},
{
"name": "kui",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "li",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "yuik",
"size": 4
},
{
"name": "yjm",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "yikm",
"size": 4
},
{
"name": "yu",
"size": 8
},
{
"name": "mmui",
"size": 4
},
{
"name": "yum",
"size": 4
},
{
"name": "kyuyy",
"size": 4
},
{
"name": "dffgy",
"size": 4
},
{
"name": "erfdr",
"size": 4
}
]
}
]
}
]
};
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var svg = d3.select("#hier").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + 500 + "," + margin.top + ")");
var div = d3.select("#hier").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
root = flare;
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
root.children.forEach(collapse);
update(root);
d3.select(self.frameElement).style("height", "800px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
nodeUpdate.select("circle")
.attr('r', function(d) {
return d.size;
})
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
})
.attr('cursor', 'pointer')
.on("mouseover", mouseover)
.on("mousemove", function(d) {
mousemove(d);
})
.on("mouseout", mouseout);
function mouseover() {
div.transition()
.duration(300)
.style("opacity", 1);
}
function mousemove(d) {
div
.text(d.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout() {
div.transition()
.duration(300)
.style("opacity", 1e-6);
}
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
</script>
</tr>
</div>
</td>
<td width="10%">
</td>
</tr>
</table>
</div>
</body>
在代码段上 运行 时,错误可重现。请帮助我理解对此的修复。
转换不是典型的选择。来自 d3v3 documentation:
A transition is a special type of selection where the operators apply
smoothly over time rather than instantaneously. You derive a
transition from a selection using the transition operator. While
transitions generally support the same operators as selections (such
as attr and style), not all operators are supported; for example, you
must append elements before a transition starts. A remove operator is
provided for convenient removal of elements when the transition ends.
您正在尝试将 .on
个事件置于转换中:
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr( .... });
nodeUpdate.select("circle")
.attr(......)
.on("mouseover", mouseover)
.on("mousemove", function(d) {
mousemove(d);
})
.on("mouseout", mouseout);
transition.select() 选择与指定选择器字符串匹配的第一个后代元素(如果有),并且 returns 对结果选择进行转换(API documentation )
但是,v3 中没有 .on
用于 d3 转换的方法。但是,有一个 .each
方法(在 v4 中重命名为 .on
)。但是,该方法允许的事件(类型)范围是三个:
If type is specified, adds a listener for transition events,
supporting "start", "end" and "interrupt" events. The listener will be
invoked for each individual element in the transition. (documentation)
不要使用转换选择来应用 .on 事件,而是尝试使用典型选择。这将允许您根据需要使用 .on。我改变了这一行
nodeUpdate.select("circle")
至
d3.selectAll("circle")
这会将 .on 事件毫无问题地应用于节点。树状图在下面的修改后的片段中似乎按预期工作:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
div.container {
width: 100%;
}
header {
height: 35px;
padding: 1em;
color: white;
background-color: gray;
clear: left;
text-align: center;
justify-content: center;
font-family: Calibri;
font-size: 35px;
font-weight: bold;
}
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 13px sans-serif;
}
.link {
fill: none;
stroke-opacity: 0.4;
stroke: purple;
stroke-width: 3.5px;
}
#content img {
position: absolute;
bottom: 0px;
right: 0px;
}
h2 {
font-family: Calibri;
font-size: 35px;
font-weight: bold;
text-align: center;
}
div.container1 span {
top: 50%;
justify-content: center;
text-align: center;
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
}
</style>
<body bgcolor='#F8F9F9'>
<script src="https://d3js.org/d3.v3.min.js"></script>
<div class="container">
<table>
<tr>
<td width="90%">
<div id="hier" align="left">
<tr>
<script>
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 1500 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var flare = {
"name": "AON",
"size": 4,
"children": [{
"name": "India",
"size": 4,
"children": [{
"name": "ARS",
"size": 4,
"children": [
{
"name": "hhh",
"size": 4
},
{
"name": "AAA",
"size": 4
},
{
"name": "BBB",
"size": 4
},
{
"name": "cCC",
"size": 8
},
{
"name": "ddd",
"size": 4
},
{
"name": "eee",
"size": 4
},
{
"name": "fff",
"size": 4
},
{
"name": "ggg",
"size": 4
},
{
"name": "hhh",
"size": 4
},
{
"name": "www",
"size": 4
},
{
"name": "qwww",
"size": 8
},
{
"name": "sd",
"size": 4
},
{
"name": "tere",
"size": 4
},
{
"name": "rtr",
"size": 4
},
{
"name": "wqw",
"size": 4
},
{
"name": "hrfg",
"size": 4
}
]
}]
},
{
"name": "Singapore",
"size": 4,
"children": [{
"name": "H&B",
"size": 4,
"children": [{
"name": "aasd",
"size": 4
},
{
"name": "sdw",
"size": 4
},
{
"name": "ghrr",
"size": 4
},
{
"name": "tyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "eds",
"size": 4
},
{
"name": "hrtr",
"size": 8
},
{
"name": "wew",
"size": 4
},
{
"name": "uyt",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "yrt",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "erewr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "kyjy",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "wew",
"size": 4
},
{
"name": "sdsf",
"size": 4
},
{
"name": "wewt",
"size": 4
},
{
"name": "wetdse",
"size": 4
},
{
"name": "wetw",
"size": 4
},
{
"name": "qwsd",
"size": 4
},
{
"name": "yrytw",
"size": 4
},
{
"name": "wewax",
"size": 4
},
{
"name": "jttut",
"size": 4
},
{
"name": "scscw",
"size": 4
},
{
"name": "wetvd",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "zc",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "zerete",
"size": 8
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "yeer",
"size": 4
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "wewretre",
"size": 4
},
{
"name": "ssdsrere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
}
]
}
]
},
{
"name": "US",
"size": 4,
"children": [{
"name": "Benfield",
"size": 4,
"children": [{
"name": "wes",
"size": 4
},
{
"name": "sd",
"size": 4
},
{
"name": "dds",
"size": 4
},
{
"name": "sdsd",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "ryr",
"size": 4
},
{
"name": "ty",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "ggrt",
"size": 4
},
{
"name": "wetyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hrfg",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hhf",
"size": 8
},
{
"name": "ere",
"size": 4
},
{
"name": "vfgd",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "xx",
"size": 4
},
{
"name": "wqwq",
"size": 4
},
{
"name": "xasa",
"size": 4
},
{
"name": "ooo",
"size": 4
},
{
"name": "ppp",
"size": 4
},
{
"name": "ll",
"size": 4
},
{
"name": "lljk",
"size": 4
},
{
"name": "kjjk",
"size": 4
},
{
"name": "kui",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "li",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "yuik",
"size": 4
},
{
"name": "yjm",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "yikm",
"size": 4
},
{
"name": "yu",
"size": 8
},
{
"name": "mmui",
"size": 4
},
{
"name": "yum",
"size": 4
},
{
"name": "kyuyy",
"size": 4
},
{
"name": "dffgy",
"size": 4
},
{
"name": "erfdr",
"size": 4
}
]
}
]
}
]
};
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var svg = d3.select("#hier").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + 500 + "," + margin.top + ")");
var div = d3.select("#hier").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
root = flare;
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
root.children.forEach(collapse);
update(root);
d3.select(self.frameElement).style("height", "800px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
d3.selectAll("circle")
.attr('r', function(d) {
return d.size;
})
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
})
.attr('cursor', 'pointer')
.on("mouseover", mouseover)
.on("mousemove", function(d) {
mousemove(d);
})
.on("mouseout", mouseout);
function mouseover() {
div.transition()
.duration(300)
.style("opacity", 1);
}
function mousemove(d) {
div
.text(d.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout() {
div.transition()
.duration(300)
.style("opacity", 1e-6);
}
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
</script>
</tr>
</div>
</td>
<td width="10%">
</td>
</tr>
</table>
</div>
</body>
我正在尝试将工具提示添加到可折叠树中,但我遇到了问题。错误似乎发生在这段代码中,如下所示(我将附上完整的代码片段以及用于调试目的)
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("circle")
.attr('r',function(d) { return d.size; })
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; })
.attr('cursor', 'pointer')
.on("mouseover", mouseover)
.on("mousemove", function(d){mousemove(d);})
.on("mouseout", mouseout);
错误消息:未捕获类型错误:nodeUpdate.select(...).attr(...).style(...).attr(.. .).on 不是函数 .on 函数未被识别为函数。我相信这与 t运行 节点的位置有关,但我不确定如何解决这个问题。
<!DOCTYPE html>
<meta charset="utf-8">
<style>
div.container {
width: 100%;
}
header {
height: 35px;
padding: 1em;
color: white;
background-color: gray;
clear: left;
text-align: center;
justify-content: center;
font-family: Calibri;
font-size: 35px;
font-weight: bold;
}
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 13px sans-serif;
}
.link {
fill: none;
stroke-opacity: 0.4;
stroke: purple;
stroke-width: 3.5px;
}
#content img {
position: absolute;
bottom: 0px;
right: 0px;
}
h2 {
font-family: Calibri;
font-size: 35px;
font-weight: bold;
text-align: center;
}
div.container1 span {
top: 50%;
justify-content: center;
text-align: center;
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
}
</style>
<body bgcolor='#F8F9F9'>
<script src="https://d3js.org/d3.v3.min.js"></script>
<div class="container">
<table>
<tr>
<td width="90%">
<div id="hier" align="left">
<tr>
<script>
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 1500 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var flare = {
"name": "AON",
"size": 4,
"children": [{
"name": "India",
"size": 4,
"children": [{
"name": "ARS",
"size": 4,
"children": [
{
"name": "hhh",
"size": 4
},
{
"name": "AAA",
"size": 4
},
{
"name": "BBB",
"size": 4
},
{
"name": "cCC",
"size": 8
},
{
"name": "ddd",
"size": 4
},
{
"name": "eee",
"size": 4
},
{
"name": "fff",
"size": 4
},
{
"name": "ggg",
"size": 4
},
{
"name": "hhh",
"size": 4
},
{
"name": "www",
"size": 4
},
{
"name": "qwww",
"size": 8
},
{
"name": "sd",
"size": 4
},
{
"name": "tere",
"size": 4
},
{
"name": "rtr",
"size": 4
},
{
"name": "wqw",
"size": 4
},
{
"name": "hrfg",
"size": 4
}
]
}]
},
{
"name": "Singapore",
"size": 4,
"children": [{
"name": "H&B",
"size": 4,
"children": [{
"name": "aasd",
"size": 4
},
{
"name": "sdw",
"size": 4
},
{
"name": "ghrr",
"size": 4
},
{
"name": "tyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "eds",
"size": 4
},
{
"name": "hrtr",
"size": 8
},
{
"name": "wew",
"size": 4
},
{
"name": "uyt",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "yrt",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "erewr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "kyjy",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "wew",
"size": 4
},
{
"name": "sdsf",
"size": 4
},
{
"name": "wewt",
"size": 4
},
{
"name": "wetdse",
"size": 4
},
{
"name": "wetw",
"size": 4
},
{
"name": "qwsd",
"size": 4
},
{
"name": "yrytw",
"size": 4
},
{
"name": "wewax",
"size": 4
},
{
"name": "jttut",
"size": 4
},
{
"name": "scscw",
"size": 4
},
{
"name": "wetvd",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "zc",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "zerete",
"size": 8
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "yeer",
"size": 4
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "wewretre",
"size": 4
},
{
"name": "ssdsrere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
}
]
}
]
},
{
"name": "US",
"size": 4,
"children": [{
"name": "Benfield",
"size": 4,
"children": [{
"name": "wes",
"size": 4
},
{
"name": "sd",
"size": 4
},
{
"name": "dds",
"size": 4
},
{
"name": "sdsd",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "ryr",
"size": 4
},
{
"name": "ty",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "ggrt",
"size": 4
},
{
"name": "wetyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hrfg",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hhf",
"size": 8
},
{
"name": "ere",
"size": 4
},
{
"name": "vfgd",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "xx",
"size": 4
},
{
"name": "wqwq",
"size": 4
},
{
"name": "xasa",
"size": 4
},
{
"name": "ooo",
"size": 4
},
{
"name": "ppp",
"size": 4
},
{
"name": "ll",
"size": 4
},
{
"name": "lljk",
"size": 4
},
{
"name": "kjjk",
"size": 4
},
{
"name": "kui",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "li",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "yuik",
"size": 4
},
{
"name": "yjm",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "yikm",
"size": 4
},
{
"name": "yu",
"size": 8
},
{
"name": "mmui",
"size": 4
},
{
"name": "yum",
"size": 4
},
{
"name": "kyuyy",
"size": 4
},
{
"name": "dffgy",
"size": 4
},
{
"name": "erfdr",
"size": 4
}
]
}
]
}
]
};
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var svg = d3.select("#hier").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + 500 + "," + margin.top + ")");
var div = d3.select("#hier").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
root = flare;
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
root.children.forEach(collapse);
update(root);
d3.select(self.frameElement).style("height", "800px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
nodeUpdate.select("circle")
.attr('r', function(d) {
return d.size;
})
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
})
.attr('cursor', 'pointer')
.on("mouseover", mouseover)
.on("mousemove", function(d) {
mousemove(d);
})
.on("mouseout", mouseout);
function mouseover() {
div.transition()
.duration(300)
.style("opacity", 1);
}
function mousemove(d) {
div
.text(d.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout() {
div.transition()
.duration(300)
.style("opacity", 1e-6);
}
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
</script>
</tr>
</div>
</td>
<td width="10%">
</td>
</tr>
</table>
</div>
</body>
在代码段上 运行 时,错误可重现。请帮助我理解对此的修复。
转换不是典型的选择。来自 d3v3 documentation:
A transition is a special type of selection where the operators apply smoothly over time rather than instantaneously. You derive a transition from a selection using the transition operator. While transitions generally support the same operators as selections (such as attr and style), not all operators are supported; for example, you must append elements before a transition starts. A remove operator is provided for convenient removal of elements when the transition ends.
您正在尝试将 .on
个事件置于转换中:
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr( .... });
nodeUpdate.select("circle")
.attr(......)
.on("mouseover", mouseover)
.on("mousemove", function(d) {
mousemove(d);
})
.on("mouseout", mouseout);
transition.select() 选择与指定选择器字符串匹配的第一个后代元素(如果有),并且 returns 对结果选择进行转换(API documentation )
但是,v3 中没有 .on
用于 d3 转换的方法。但是,有一个 .each
方法(在 v4 中重命名为 .on
)。但是,该方法允许的事件(类型)范围是三个:
If type is specified, adds a listener for transition events, supporting "start", "end" and "interrupt" events. The listener will be invoked for each individual element in the transition. (documentation)
不要使用转换选择来应用 .on 事件,而是尝试使用典型选择。这将允许您根据需要使用 .on。我改变了这一行
nodeUpdate.select("circle")
至
d3.selectAll("circle")
这会将 .on 事件毫无问题地应用于节点。树状图在下面的修改后的片段中似乎按预期工作:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
div.container {
width: 100%;
}
header {
height: 35px;
padding: 1em;
color: white;
background-color: gray;
clear: left;
text-align: center;
justify-content: center;
font-family: Calibri;
font-size: 35px;
font-weight: bold;
}
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 13px sans-serif;
}
.link {
fill: none;
stroke-opacity: 0.4;
stroke: purple;
stroke-width: 3.5px;
}
#content img {
position: absolute;
bottom: 0px;
right: 0px;
}
h2 {
font-family: Calibri;
font-size: 35px;
font-weight: bold;
text-align: center;
}
div.container1 span {
top: 50%;
justify-content: center;
text-align: center;
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
}
</style>
<body bgcolor='#F8F9F9'>
<script src="https://d3js.org/d3.v3.min.js"></script>
<div class="container">
<table>
<tr>
<td width="90%">
<div id="hier" align="left">
<tr>
<script>
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 1500 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var flare = {
"name": "AON",
"size": 4,
"children": [{
"name": "India",
"size": 4,
"children": [{
"name": "ARS",
"size": 4,
"children": [
{
"name": "hhh",
"size": 4
},
{
"name": "AAA",
"size": 4
},
{
"name": "BBB",
"size": 4
},
{
"name": "cCC",
"size": 8
},
{
"name": "ddd",
"size": 4
},
{
"name": "eee",
"size": 4
},
{
"name": "fff",
"size": 4
},
{
"name": "ggg",
"size": 4
},
{
"name": "hhh",
"size": 4
},
{
"name": "www",
"size": 4
},
{
"name": "qwww",
"size": 8
},
{
"name": "sd",
"size": 4
},
{
"name": "tere",
"size": 4
},
{
"name": "rtr",
"size": 4
},
{
"name": "wqw",
"size": 4
},
{
"name": "hrfg",
"size": 4
}
]
}]
},
{
"name": "Singapore",
"size": 4,
"children": [{
"name": "H&B",
"size": 4,
"children": [{
"name": "aasd",
"size": 4
},
{
"name": "sdw",
"size": 4
},
{
"name": "ghrr",
"size": 4
},
{
"name": "tyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "eds",
"size": 4
},
{
"name": "hrtr",
"size": 8
},
{
"name": "wew",
"size": 4
},
{
"name": "uyt",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "yrt",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "erewr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "kyjy",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "wew",
"size": 4
},
{
"name": "sdsf",
"size": 4
},
{
"name": "wewt",
"size": 4
},
{
"name": "wetdse",
"size": 4
},
{
"name": "wetw",
"size": 4
},
{
"name": "qwsd",
"size": 4
},
{
"name": "yrytw",
"size": 4
},
{
"name": "wewax",
"size": 4
},
{
"name": "jttut",
"size": 4
},
{
"name": "scscw",
"size": 4
},
{
"name": "wetvd",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "zc",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "zerete",
"size": 8
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "yeer",
"size": 4
},
{
"name": "sdaxa",
"size": 4
},
{
"name": "wewretre",
"size": 4
},
{
"name": "ssdsrere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
},
{
"name": "asdsdere",
"size": 4
}
]
}
]
},
{
"name": "US",
"size": 4,
"children": [{
"name": "Benfield",
"size": 4,
"children": [{
"name": "wes",
"size": 4
},
{
"name": "sd",
"size": 4
},
{
"name": "dds",
"size": 4
},
{
"name": "sdsd",
"size": 4
},
{
"name": "ere",
"size": 4
},
{
"name": "ryr",
"size": 4
},
{
"name": "ty",
"size": 4
},
{
"name": "wewe",
"size": 4
},
{
"name": "ggrt",
"size": 4
},
{
"name": "wetyr",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hrfg",
"size": 4
},
{
"name": "wew",
"size": 4
},
{
"name": "hhf",
"size": 8
},
{
"name": "ere",
"size": 4
},
{
"name": "vfgd",
"size": 4
}
]
},
{
"name": "GCP",
"size": 4,
"children": [{
"name": "xx",
"size": 4
},
{
"name": "wqwq",
"size": 4
},
{
"name": "xasa",
"size": 4
},
{
"name": "ooo",
"size": 4
},
{
"name": "ppp",
"size": 4
},
{
"name": "ll",
"size": 4
},
{
"name": "lljk",
"size": 4
},
{
"name": "kjjk",
"size": 4
},
{
"name": "kui",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "li",
"size": 4
},
{
"name": "uyu",
"size": 4
},
{
"name": "yuik",
"size": 4
},
{
"name": "yjm",
"size": 4
},
{
"name": "yu",
"size": 4
},
{
"name": "yikm",
"size": 4
},
{
"name": "yu",
"size": 8
},
{
"name": "mmui",
"size": 4
},
{
"name": "yum",
"size": 4
},
{
"name": "kyuyy",
"size": 4
},
{
"name": "dffgy",
"size": 4
},
{
"name": "erfdr",
"size": 4
}
]
}
]
}
]
};
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
var svg = d3.select("#hier").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + 500 + "," + margin.top + ")");
var div = d3.select("#hier").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
root = flare;
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
root.children.forEach(collapse);
update(root);
d3.select(self.frameElement).style("height", "800px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180;
});
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
d3.selectAll("circle")
.attr('r', function(d) {
return d.size;
})
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
})
.attr('cursor', 'pointer')
.on("mouseover", mouseover)
.on("mousemove", function(d) {
mousemove(d);
})
.on("mouseout", mouseout);
function mouseover() {
div.transition()
.duration(300)
.style("opacity", 1);
}
function mousemove(d) {
div
.text(d.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
}
function mouseout() {
div.transition()
.duration(300)
.style("opacity", 1e-6);
}
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
</script>
</tr>
</div>
</td>
<td width="10%">
</td>
</tr>
</table>
</div>
</body>