我正在使用d3.js版本5以及circle-pack和d3弧生成器。 Circle pack和缩放代码是标准的,并在许多地方使用。当我尝试沿圆弧放置弧形文本时,它可以正常工作并且可以很好地加载,但是当我尝试放大或缩小时,文本/标签并没有相应地与圆弧边界一起放置。这是我的代码:https://codepen.io/dmd7/pen/BvMwbr
我尝试过'd3-circle-text' on zoomable circle-pack中在此处提到的“ d3-circle-text”插件,但由于它使用的是较早版本的d3,并且放大功能有所不同,因此无法正常工作。
此外,我想尝试一下这里实现的目标:http://nbremer.github.io/occupations/,但由于再次从较旧的d3版本转换为较新的d3版本而使工作变得更加困难,因此无法正常工作。
这是我的代码:https://codepen.io/dmd7/pen/BvMwbr
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>test</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
text {
font-size: 11px;
}
text.parent {
fill: #1f77b4;
}
text {
font: 10px sans-serif;
}
/*.text {
cursor: pointer;
}*/
text:hover {
/*color: #FF0000; */
font-weight: bold;
stroke: #000;
stroke-width: 0.5px;
text-decoration: underline;
}
circle {
fill: #ccc;
stroke: #999;
pointer-events: all;
cursor: pointer;
opacity: 0.55;
}
circle.parent {
fill: #1f77b4;
fill-opacity: .1;
stroke: steelblue;
}
circle.parent:hover {
stroke: #ff7f0e;
stroke-width: .5px;
}
/*circle.child {
pointer-events: none;
}*/
/*Node hover*/
/*.node {
cursor: pointer;
}
.node:hover {
stroke: #000;
stroke-width: 1.5px;
}
.node--leaf {
fill: white;
}
*/
/*Circle text*/
.label {
font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
text-anchor: middle;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
}
.label,
.node--root,
.node--leaf {
pointer-events: none;
}
.arc-path {
visibility: hidden;
}
</style>
</head>
<body>
<div id="container">
<svg width="700" height="700" id="cir_svg"></svg>
</div>
</body>
</html>
这是javaScript代码:
var svg, margin, diameter, g, pack, focus, view, circle, node;
var maxNumLevels = 3;
document.addEventListener("DOMContentLoaded", function (e) {
svg = d3.select("svg"),
margin = 20,
diameter = +svg.attr("width");
g = svg.append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
pack = d3.pack()
.size([diameter - margin, diameter - margin])
.padding(2);
initialSpecialCase();
});
function generateLevels(pivotLevel) {
pivNum = parseInt(pivotLevel.match(/VirusL(\d+)_s/)[1]);
var r = '';
for (var n = 0; n <= maxNumLevels; ++n) {
if(n!=0) {
r += ",";
}
r += "VirusL" + (pivNum + n) + "_s";
}
curLevelsStr = r;
return r;
}
function extractTaxIdFromName(nameTaxId) {
var idx = nameTaxId.lastIndexOf(", taxid:");
if(idx != -1) {
return nameTaxId.substring(idx + 8);
}
return '';
}
function initialSpecialCase() {
var data1 = {};
d3.json("https://api.myjson.com/bins/1h5co8").then(function(dta) {
console.info("Data from ajax: ", dta);
data1 = {
'name' : 'root',
'field' : '',
'value' : dta.response.numFound,
'pivot' : dta['facet_counts']['facet_pivot'][generateLevels('VirusL0_s')]
};
createCircles(data1);
});
}
function mapData(d) {
if (!d.hasOwnProperty('pivot'))
return;
d.hasChildren = true;
var maxPivName = "VirusL" + (pivNum + maxNumLevels - 1).toString() + "_s";
if (d.field === maxPivName)
return;
var cnodes = d.pivot;
for (c in cnodes) {
if (!cnodes[c].hasOwnProperty('name')) {
cnodes[c].name = cnodes[c].value;
cnodes[c].value = cnodes[c].count;
}
}
return cnodes;
}
function arcSVG(mx0, my0, r, larc, sweep, mx1, my1) {
return 'M'+mx0+','+my0+' A'+r+','+r+' 0 '+larc+','+sweep+' '+mx1+','+my1;
}
function createCircles(data) {
var root = d3.hierarchy(data, mapData)
.sort(function(a, b) { return b.value - a.value; });
console.info(root);
focus = root;
var nodes = pack(root).descendants();
var nodeg = g.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", function(d) {
return d.children ? "node" : "leaf node";
})
;
nodeg.append("circle")
.attr("class", function(d) { return d.children ? "parent" : "child"; })
.attr("id", function(d) { return 'c' + extractTaxIdFromName(d.data.name); })
.on("click", function(d) {
selectedVirus = d.data.name;
if (!d.children && d.parent) {
zoom(d); d3.event.stopPropagation();
}
else if (focus !== d) {
zoom(d);
d3.event.stopPropagation();
}
});
nodeg.append("title")
.text(function(d) {
return d.data.name;
});
nodeg.each(function(d, i) {
var gg = d3.select(this);
if(d.depth === 3) {
// gg.append('text')
// .style('font-size', d3.min([3 * d.r / d.data.name.length, 16]))
// .attr('dy', '0.3em')
// .text(d.data.name);
}
else if(d.depth > 0) {
var rr = d.r - 5;
gg.append('path')
.attr('d', arcSVG(-rr, 0, rr, 1, 1, rr, 0))
.attr('id', 'label-path-' + i)
.style('fill', 'none')
.style('stroke', 'none');
gg.append('text')
.append('textPath')
.attr('xlink:href', '#label-path-' + i)
.attr('startOffset', '50%')
.style("text-anchor","middle")
.style('font-size', '10px')
.style('fill', 'black')
.text(d.data.name);
}
});
node = nodeg.selectAll("circle,text");
circle = nodeg.selectAll("circle");
svg
.on("click", function() {
zoom(root);
});
zoomTo([root.x, root.y, root.r * 2 + margin]);
}
function zoom(d) {
var focus0 = focus; focus = d;
var transition = d3.transition()
.duration(d3.event.altKey ? 7500 : 750)
.tween("zoom", function(d) {
var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
return function(t) { zoomTo(i(t)); };
});
transition.selectAll("text")
.filter(function(d) { return d.parent === focus || this.style.display === "inline"; })
.style("fill-opacity", function(d) { return d.parent === focus ? 1 : 0; })
.on("start", function(d) { if (d.parent === focus) this.style.display = "inline"; })
.on("end", function(d) { if (d.parent !== focus) this.style.display = "none"; });
}
function zoomTo(v) {
var k = diameter / v[2]; view = v;
node.attr("transform", function(d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
circle.attr("r", function(d) { return d.r * k; });
}
感谢您的帮助。
谢谢。
答案 0 :(得分:2)
您没有在缩放功能中选择<textPath>
的路径。可以这样完成:
svg.selectAll("path")
.attr('d', function(d){
return arcSVG(-(d.r - 5) * k, 0, (d.r - 5) * k, 1, 1, (d.r - 5) * k, 0)
});
当然,一个更好的主意是命名您的选择,并改进新的d
属性。另外,请记住创建全局变量(例如circle
和node
),只是为了在缩放功能中使用它们。最后,您用于设置文本路径的display
属性的逻辑无法正常工作。
以下是分叉的Codepen:https://codepen.io/anon/pen/QzYawj?editors=0010