我正在尝试创建SVG视图,其中,我需要根据矩形中数据的升序将矩形放在一行中。
矩形应根据值的差异放置在距左侧适当的距离处。
这是我到现在为止所得到的。但是,如果我使用线性刻度,我的矩形是重叠的。有没有办法可以避免这些矩形的重叠?
更新:
我们决定在同一级别上显示重叠的矩形和不重叠的矩形。但现在的问题是如何进行平移并通过更新y轴将矩形放在另一个下面。现在需要预先确定重叠,并且需要确定x和y坐标以进行转换。问题是复杂的,因为矩形大小可能会根据其中的文本大小而变化。
任何建议都将不胜感激。
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
var data = [{
x: 20,
y: 10,
baseFare: 50,
class : "L"
},
{
x: 100,
y: 10,
baseFare: 100,
class : "K"
}, {
x: 200,
y : 10,
baseFare : 230,
class : "R"
},
{
x: 500,
y : 10,
baseFare : 1000,
class : "R"
},
{
x: 500,
y : 10,
baseFare : 400,
class : "M"
},
{
x: 500,
y : 10,
baseFare : 300,
class : "N"
},
{
x: 500,
y : 10,
baseFare : 380,
class : "Q"
}
];
data = data.sort(function (a, b) {
return d3.ascending(a.baseFare, b.baseFare);
})
var width = 2000;
var height = 500;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var xExtent = d3.extent(data, function(d) { return d.baseFare; });
var xRange = xExtent[1] - xExtent[0];
var linearScale = d3.scale.linear()
.range([0, 500])
.domain([d3.min(data, function (d) {
return d.baseFare;
}), d3.max(data, function (d) {
return d.baseFare;
})]);
var y = 10;
for (var i = 0; i < data.length; i++) {
data[i].x = linearScale(data[i].baseFare);
}
var g = svg.selectAll('.someClass')
.data(data)
.enter()
.append("g")
.attr("class","someClass")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
g.append("rect")
.attr("width", 40)
.attr("height", 40)
.attr("rx", 10)
.attr("ry", 10)
.attr("stroke", "black")
.attr("stroke-opacity", 0.8)
.style("fill", "lightblue");
g.append("text")
.style("fill", "black")
.attr("x", 15)
.attr("y", 10)
.style("alignment-baseline", "middle")
.text(function(d) {
return d.class;
})
g.append("text")
.style("fill", "black")
.attr("x", 5)
.attr("y", 30)
.style("alignment-baseline", "middle")
.text(function(d) {
return "$" + d.baseFare;
})
</script>
</body>
</html>
&#13;
答案 0 :(得分:0)
确定要应用于给定矩形的x平移时,可以检查此x平移是否会使此新矩形与前一个矩形重叠。如果是这种情况,则应用前一个矩形的平移加上矩形的宽度。
您可以替换:
for (var i = 0; i < data.length; i++) {
data[i].x = linearScale(data[i].baseFare);
}
使用:
for (var i = 0; i < data.length; i++) {
data[i].x = linearScale(data[i].baseFare);
if (i > 0 && data[i - 1].x + 40 > data[i].x)
data[i].x = data[i - 1].x + 41;
}
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
var data = [
{
x: 20,
y: 10,
baseFare: 50,
class : "L"
},
{
x: 100,
y: 10,
baseFare: 100,
class : "K"
},
{
x: 200,
y: 10,
baseFare : 230,
class : "R"
},
{
x: 500,
y: 10,
baseFare : 1000,
class : "R"
},
{
x: 500,
y: 10,
baseFare : 400,
class : "M"
},
{
x: 500,
y: 10,
baseFare : 300,
class : "N"
},
{
x: 500,
y: 10,
baseFare : 380,
class : "Q"
}
];
data = data.sort(function (a, b) {
return d3.ascending(a.baseFare, b.baseFare);
})
var svg = d3.select("body").append("svg").attr("width", 2000).attr("height", 500);
var xExtent = d3.extent(data, function(d) { return d.baseFare; });
var xRange = xExtent[1] - xExtent[0];
var linearScale = d3.scale.linear()
.range([0, 500])
.domain([
d3.min(data, function (d) { return d.baseFare; }),
d3.max(data, function (d) { return d.baseFare; })
]);
var y = 10;
for (var i = 0; i < data.length; i++) {
data[i].x = linearScale(data[i].baseFare);
if (i > 0 && data[i - 1].x + 40 > data[i].x)
data[i].x = data[i - 1].x + 41;
}
var g = svg.selectAll('.someClass')
.data(data)
.enter()
.append("g")
.attr("class","someClass")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
g.append("rect")
.attr("width", 40)
.attr("height", 40)
.attr("rx", 10)
.attr("ry", 10)
.attr("stroke", "black")
.attr("stroke-opacity", 0.8)
.style("fill", "lightblue");
g.append("text")
.style("fill", "black")
.attr("x", 15)
.attr("y", 10)
.style("alignment-baseline", "middle")
.text(function(d) { return d.class; })
g.append("text")
.style("fill", "black")
.attr("x", 5)
.attr("y", 30)
.style("alignment-baseline", "middle")
.text(function(d) { return "$" + d.baseFare; })
</script>
</body>
</html>