如何在D3.js v3.4平行坐标中标记线轴交点并移除刻度?
解决D3.js v3.4平行坐标分类数据交点显示类别名称的问题
问题说明
我正在使用D3.js v3.4实现平行坐标来可视化分类数据,希望线条与坐标轴的交点处显示对应的类别名称,效果可参考附图。
当前代码
d3.csv("/static/testQuantifized.csv", function(error, coffee) { x.domain(dimensions = d3.keys(coffee[0]).filter(function(d) { // console.log(d); if(d == "" ||d == "Country of Origin" ||d == "Variety" ||d == "Processing Method" || d == "Altitude" || d == "Grading Date" || d == "Altitude" || d == "Balance" || d =="uniformity" || d == "Clean Cup" || d =="Sweetness" || d == "Defects" || d == "Total Cup Points" || d =="Moisture Percentage" || d =="Category One Defects" || d =="Quakers" || d == "Color" || d == "Category Two Defects" || d == "Expiration") return false; // if(d == "Country of Origin" || "Variety" || "Processing Method") { // y[d] = d3.scale.ordinal() // .domain(coffee.map(function(p) { return p[d]; })) // .rangePoints([h, 0]); // } else if(d == "Aroma" || "Flavor" || "Aftertaste" || "Acidity" || "Body" || "Overall") { y[d] = d3.scale.linear() .domain(d3.extent(coffee, function(p) { return +p[d]; })) .range([h, 0]); } return true; })); // Add an axis and title. g.append("svg:g") .attr("class", "axis") .each(function(d) { d3.select(this).call(axis.scale(y[d])); }) .append("svg:text") .attr("text-anchor", "middle") .attr("y", -9) .text(String);
解决方案
要实现线条与坐标轴交点处显示类别名称,需完成以下步骤:
- 修正分类变量的比例尺配置
取消注释的分类字段比例尺代码,同时修正条件判断逻辑(原代码中多条件判断写法有误,需逐个判断d ==):
if(d == "Country of Origin" || d == "Variety" || d == "Processing Method") { y[d] = d3.scale.ordinal() .domain(d3.set(coffee.map(function(p) { return p[d]; })).values()) // 对类别值去重 .rangePoints([h, 0]); }
- 在线条交点处添加类别文本标签
绘制完平行坐标线条后,遍历每个数据项和维度,在对应位置生成文本标签:
// 假设已定义平行坐标线条绘制代码 g.selectAll(".line") .data(coffee) .enter().append("path") .attr("class", "line") .attr("d", function(d) { return d3.svg.line()(dimensions.map(function(p) { return [x(p), y[p](d[p])]; })); }); // 添加类别文本标签 g.selectAll(".dimension-label") .data(coffee) .enter().selectAll(".label-item") .data(function(d) { return dimensions.map(function(p) { return { value: d[p], x: x(p), y: y[p](d[p]) }; }); }) .enter().append("text") .attr("class", "label-item") .attr("x", function(d) { return d.x; }) .attr("y", function(d) { return d.y; }) .attr("dy", "0.35em") .attr("text-anchor", function(d) { // 根据横轴位置调整文本对齐方向,避免超出画布 return d.x < width/2 ? "start" : "end"; }) .attr("dx", function(d) { return d.x < width/2 ? 3 : -3; }) .text(function(d) { return d.value; });
- 确保分类坐标轴刻度正常显示
分类坐标轴直接使用d3.svg.axis()即可,ordinal比例尺默认会将domain中的类别值作为刻度文本:
var axis = d3.svg.axis() .orient("left") .tickSize(6) .tickPadding(8);
优化提示
- 若标签出现重叠,可通过缩小字体、设置透明度,或添加hover交互(仅鼠标悬停时显示标签)优化显示效果。
- 确认
x比例尺为平行坐标横轴的ordinal比例尺,通常定义为:var x = d3.scale.ordinal().domain(dimensions).rangePoints([0, width])。
内容的提问来源于stack exchange,提问作者Naxatra
相关产品推荐
相关产品推荐

