我正在使用 D3 (v3) 創建一個分層邊束圖。我需要我的文本標簽在其中包含括號(例如“name”:“root.b.yes(1)”),但是,當將滑鼠懸停在標簽上時,這似乎會阻止行突出顯示。根據控制臺,這會使選擇器無效。我已經包含了一個最小示例的代碼,其中只有兩個相互連接的標簽。如果我洗掉了 data.json 檔案中的括號,則在懸停時正確突出顯示行,如果包含括號,則沒有行突出顯示。我不確定為什么不允許使用括號,到目前為止我還沒有找到解決這個問題的任何幫助。
控制臺錯誤資訊
Uncaught DOMException: Failed to execute 'querySelector' on 'Element': '#node-yes(1)' is not a valid selector.
html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<link type="text/css" rel="stylesheet" href="style.css"/>
<style type="text/css">
path.arc {
cursor: move;
fill: #fff;
}
.node {
font-size: 10px;
}
.node:hover {
fill: #1f77b4;
}
.link {
fill: none;
stroke: #1f77b4;
stroke-opacity: .4;
pointer-events: none;
}
.link.source, .link.target {
stroke-opacity: 1;
stroke-width: 2px;
}
.node.target {
fill: #d62728 !important;
}
.link.source {
stroke: #d62728;
}
.node.source {
fill: #2ca02c;
}
.link.target {
stroke: #2ca02c;
}
</style>
</head>
<body>
<h2>
</h2>
<div id="bundle"></div>
<div style="position:absolute;bottom:0;font-size:18px;">tension: <input style="position:relative;top:3px;" type="range" min="0" max="100" value="85"></div>
<script type="text/javascript" src="//code.jquery.com/jquery-1.12.3.min.js"></script>
<script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="packages.js"></script>
<script type="text/javascript">
var w = 740,
h = 700,
rx = w / 2,
ry = h / 2,
m0,
rotate = 0
pi = Math.PI;
var splines = [];
var cluster = d3.layout.cluster()
.size([360, ry - 180])
.sort(function(a, b) { return d3.ascending(a.key, b.key); });
var bundle = d3.layout.bundle();
var line = d3.svg.line.radial()
.interpolate("bundle")
.tension(.85)
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
// Chrome 15 bug: <http://code.google.com/p/chromium/issues/detail?id=98951>
var div = d3.select("#bundle")
.style("width", w "px")
.style("height", w "px")
.style("position", "absolute");
var svg = div.append("svg:svg")
.attr("width", w)
.attr("height", w)
.append("svg:g")
.attr("transform", "translate(" rx "," ry ")");
svg.append("svg:path")
.attr("class", "arc")
.attr("d", d3.svg.arc().outerRadius(ry - 180).innerRadius(0).startAngle(0).endAngle(2 * Math.PI))
.on("mousedown", mousedown);
d3.json("data.json", function(classes) {
var nodes = cluster.nodes(packages.root(classes)),
links = packages.imports(nodes),
splines = bundle(links);
var path = svg.selectAll("path.link")
.data(links)
.enter().append("svg:path")
.attr("class", function(d) { return "link source-" d.source.key " target-" d.target.key; })
.attr("d", function(d, i) { return line(splines[i]); });
var groupData = svg.selectAll("g.group")
.data(nodes.filter(function(d) { return (d.key=='a' || d.key == 'b') && d.children; }))
.enter().append("group")
.attr("class", "group");
var groupArc = d3.svg.arc()
.innerRadius(ry - 177)
.outerRadius(ry - 157)
.startAngle(function(d) { return (findStartAngle(d.__data__.children)-2) * pi / 180;})
.endAngle(function(d) { return (findEndAngle(d.__data__.children) 2) * pi / 180});
svg.selectAll("g.arc")
.data(groupData[0])
.enter().append("svg:path")
.attr("d", groupArc)
.attr("class", "groupArc")
.style("fill", "#1f77b4")
.style("fill-opacity", 0.5);
svg.selectAll("g.node")
.data(nodes.filter(function(n) { return !n.children; }))
.enter().append("svg:g")
.attr("class", "node")
.attr("id", function(d) { return "node-" d.key; })
.attr("transform", function(d) { return "rotate(" (d.x - 90) ")translate(" d.y ")"; })
.append("svg:text")
.attr("dx", function(d) { return d.x < 180 ? 25 : -25; })
.attr("dy", ".31em")
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
.text(function(d) { return d.key.replace(/_/g, ' '); })
.on("mouseover", mouseover)
.on("mouseout", mouseout);
d3.select("input[type=range]").on("change", function() {
line.tension(this.value / 100);
path.attr("d", function(d, i) { return line(splines[i]); });
});
});
d3.select(window)
.on("mousemove", mousemove)
.on("mouseup", mouseup);
function mouse(e) {
return [e.pageX - rx, e.pageY - ry];
}
function mousedown() {
m0 = mouse(d3.event);
d3.event.preventDefault();
}
function mousemove() {
if (m0) {
var m1 = mouse(d3.event),
dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI;
div.style("-webkit-transform", "translate3d(0," (ry - rx) "px,0)rotate3d(0,0,0," dm "deg)translate3d(0," (rx - ry) "px,0)");
}
}
function mouseup() {
if (m0) {
var m1 = mouse(d3.event),
dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI;
rotate = dm;
if (rotate > 360) rotate -= 360;
else if (rotate < 0) rotate = 360;
m0 = null;
div.style("-webkit-transform", "rotate3d(0,0,0,0deg)");
svg.attr("transform", "translate(" rx "," ry ")rotate(" rotate ")")
.selectAll("g.node text")
.attr("dx", function(d) { return (d.x rotate) % 360 < 180 ? 25 : -25; })
.attr("text-anchor", function(d) { return (d.x rotate) % 360 < 180 ? "start" : "end"; })
.attr("transform", function(d) { return (d.x rotate) % 360 < 180 ? null : "rotate(180)"; });
}
}
function mouseover(d) {
svg.selectAll("path.link.target-" d.key)
.classed("target", true)
.each(updateNodes("source", true));
svg.selectAll("path.link.source-" d.key)
.classed("source", true)
.each(updateNodes("target", true));
}
function mouseout(d) {
svg.selectAll("path.link.source-" d.key)
.classed("source", false)
.each(updateNodes("target", false));
svg.selectAll("path.link.target-" d.key)
.classed("target", false)
.each(updateNodes("source", false));
}
function updateNodes(name, value) {
return function(d) {
if (value) this.parentNode.appendChild(this);
svg.select("#node-" d[name].key).classed(name, value);
};
}
function cross(a, b) {
return a[0] * b[1] - a[1] * b[0];
}
function dot(a, b) {
return a[0] * b[0] a[1] * b[1];
}
function findStartAngle(children) {
var min = children[0].x;
children.forEach(function(d) {
if (d.x < min)
min = d.x;
});
return min;
}
function findEndAngle(children) {
var max = children[0].x;
children.forEach(function(d) {
if (d.x > max)
max = d.x;
});
return max;
}
</script>
</body>
</html>
json
[
{"name":"root.a.no","imports":["root.b.yes(1)"]},
{"name":"root.b.yes(1)","imports":[]}
]
css
body {
font: 300 36px "Helvetica Neue";
height: 640px;
/*margin: 80px 160px 80px 160px;
overflow: hidden;*/
position: relative;
}
a:link, a:visited {
color: rgb(202, 0, 0);
text-decoration: none;
}
a:hover {
color: rgb(245, 6, 6);
}
.invert {
background: #1f1f1f;
color: #dcdccc;
}
.invert h2, .invert h3 {
color: #3eec3e;
}
.string, .regexp {
color: #f39;
}
.keyword {
color: #00c;
}
.comment {
color: rgb(255, 28, 28);
font-style: oblique;
}
.number {
color: rgb(255, 21, 21);
}
.class, .special {
color: #1181B8;
}
body > svg {
position: absolute;
top: -80px;
left: -160px;
}
我知道 D3 的未來版本允許在文本標簽中使用括號,但我需要專門使用版本 3。
任何幫助表示贊賞。
uj5u.com熱心網友回復:
我認為有兩件事可以奏效:
嘗試為查詢字串添加轉義反斜杠
如果在那之后,d3v3 仍然不直接支持這個,我相信解決方法是通過選擇HTML 節點而不是選擇器字串。因此,您可以執行以下操作:
const node = document.querySelector('#node-yes(1)') d3.select(node).classed(...)
再說一次,如果它不起作用,請嘗試在選擇時轉義括號:(編輯)
const parsedKey = d[name].key.replace("(", "\\(").replace(")", "\\)")
svg.select("#node-" parsedKey).classed(name, value)
. 我相信如果這兩個選項都不起作用,那么你需要提高 d3 的版本
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/489937.html
標籤:javascript html css svg d3.js
