我正在尝试学习d3来构建可视化;作为这个项目的一部分,我发现我需要绘制一些填充的矩形。这在SVG坐标中应该是直截了当的,但我想绘制数据坐标。我无法弄清楚为什么任何矩形会被画在画布之外,但这就是我在这里的最小(非)工作示例中所观察到的:https://bl.ocks.org/emprice/faed364cb1bc4cc1b0dcf8a5a2d50dac。
粉红色矩形实际上超出了SVG元素的边界,如果我正确设置了x和y映射,这没有意义。是否有绘制数据坐标的技巧,我没有使用过,或者我是否错误地配置了刻度?我试过改变y比例参数(范围和域)但没有成功;以相同方式设置的x刻度似乎按预期工作。
提前感谢您的帮助。
答案 0 :(得分:1)
请记住,svg坐标从顶部开始,高度向下延伸矩形。如果你替换这一行:
.attr("y", function(d) { return y(d.y0); })
与
.attr("y", function(d) { return height- y(d.y0); })
你会得到一些看起来更合适的东西。
例如,y坐标为y1:2且y0:0的矩形。此矩形用于填充svg的整个高度。使用你的比例:
var y = d3.scaleLinear().rangeRound([height, 0]).domain([0., 2.]);
和你的y位置:
.attr("y", function(d) { return y(d.y0); })
您将把这个矩形的顶部放在svg的底部。对于输入y值为0,比例将返回等于height
的值。使用svg y坐标height
放置的任何内容都位于svg的底部。
矩形的高度也将等于height
,因此矩形将从svg向下延伸(矩形的一部分将因为使用代码的边距而可见)。
相反,此矩形应显示在顶部,并一直向下延伸,为此,从height
中减去缩放值,矩形将显示在svg的顶部。< / p>
如果您希望屏幕底部显示输入y值为零,而不是顶部(更典型的笛卡尔设置的抛弃SVG约定),那么您需要根据比例更改一点:< / p>
var y = d3.scaleLinear().rangeRound([0, height]).domain([0., 2.]);
和身高:
.attr("height", function(d) { return y(d.y1) - y(d.y0); })
并更改它,以便将顶部坐标放在rect的顶部:
.attr("y", function(d) { return y(d.y1); })
答案 1 :(得分:1)
在这个答案中,我不会解决other answer中涵盖的坐标问题,但我会给你两个重要的建议:
关于第2点,由于你的数据是一个对象而且data
方法不接受一个对象,我们把它变成一个数组......
var dataArray = [];
for (var key in data) {
dataArray.push({
category: key,
y1: data[key][0].y1,
y0: data[key][0].y0,
x1: data[key][0].x1,
x0: data[key][0].x0,
})
}
...我们可以用来惯用绑定数据:
g.selectAll(null)
.data(dataArray)
.enter()
.append("rect")
以下是包含这些更改的代码:
<script src="https://d3js.org/d3.v4.min.js">
</script>
<script type="text/javascript">
var data = {
"cat1": [{
"y1": 1.581699235490658,
"y0": 0.8124126240209036,
"x0": 0.0003786444528587656,
"x1": 0.23513820522529344
}],
"cat2": [{
"y1": 1.438932516124979,
"y0": 0.7292493003174502,
"x0": 0.0003786444528587656,
"x1": 0.3029155622870125
}, {
"y1": 0.816326356719349,
"y0": 0.7577181178689592,
"x0": 0.471790988262022,
"x1": 1.0
}],
"cat3": [{
"y1": 1.04308128481062,
"y0": 0.5216497481615152,
"x0": 0.0,
"x1": 0.3029155622870125
}, {
"y1": 1.2796737272400311,
"y0": 0.5443780228140943,
"x0": 0.471790988262022,
"x1": 1.0
}],
"cat4": [{
"y1": 0.8577183187799378,
"y0": 0.5507803277857598,
"x0": 0.44377129875047333,
"x1": 0.4714123438091632
}],
"cat5": [{
"y1": 1.411106314679798,
"y0": 0.6447611230842676,
"x0": 0.3032942067398713,
"x1": 0.4714123438091632
}],
"cat6": [{
"y1": 0.9875866563383724,
"y0": 0.5832528539336078,
"x0": 0.2355168496781522,
"x1": 1.0
}],
"cat7": [{
"y1": 1.2362146708036688,
"y0": 0.2743087520017313,
"x0": 0.3032942067398713,
"x1": 0.44339265429761454
}]
};
var dataArray = [];
for (var key in data) {
dataArray.push({
category: key,
y1: data[key][0].y1,
y0: data[key][0].y0,
x1: data[key][0].x1,
x0: data[key][0].x0,
})
}
// define the dimensions of the graph pane
var margin = {
top: 30,
right: 30,
bottom: 30,
left: 30
};
var width = 400 - margin.left - margin.right;
var height = 200 - margin.top - margin.bottom;
// define the scale
var x = d3.scaleLinear().rangeRound([0, width]).domain([0., 1.]);
var y = d3.scaleLinear().rangeRound([0, height]).domain([0., 2.]);
var z = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.selectAll(null).data(dataArray).enter()
.append("rect")
.attr("x", function(d) {
return x(d.x0);
})
.attr("y", function(d) {
return y(d.y0);
})
.attr("width", function(d) {
return x(d.x1) - x(d.x0);
})
.attr("height", function(d) {
return y(d.y1) - y(d.y0);
})
.attr("fill", function(d) {
return z(d.category);
});
</script>