D3 v4 将数据缩放到范围



数据未正确缩放到范围。

我正在将 svg 附加到div,

var svg = d3.select("#box")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);

然后是该 SVG 的组。

// create group
var group = svg.append("g")
.attr("class", "main_group")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

然后缩放 x 轴,

var x = d3.scaleLinear()
.domain(0, d3.max(function(d) {
return d.x_pos
})).range([0, width]);

宽度设置为,

var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = 600 - margin.left - margin.right, // width=500
height = 600 - margin.top - margin.bottom; // height=500

当我将x_pos值更改为大于 800 时,渲染的矩形在 svg 之外。目前在 x_pos=525 处,矩形的左上角可见。

{ 
// "x_pos": "800",
"x_pos": "525",
"y_pos": "300",
"name": "Dd"
},

我希望数据中的x_pos值始终缩放到范围 [0,宽度]。

为什么数据没有缩放到范围?

GitHub 和 GH-pages 演示

svg {
border: 2px solid gray;
}
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="box">
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
data = [{
"x_pos": "100",
"y_pos": "400",
"name": "Aa"
},
{
"x_pos": "200",
"y_pos": "200",
"name": "Bb"
},
{
"x_pos": "300",
"y_pos": "100",
"name": "Cc"
},
{
// "x_pos": "300",
"x_pos": "525",
"y_pos": "300",
"name": "Dd"
},
{
"x_pos": "0",
"y_pos": "0",
"name": "Ee"
}
]
data.forEach(function(d) {
d.x_pos = +d.x_pos;
d.y_pos = +d.y_pos;
});
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = 600 - margin.left - margin.right, // width=500
height = 600 - margin.top - margin.bottom; // height=500
var x = d3.scaleLinear()
.domain(0, d3.max(function(d) {
return d.x_pos
})).range([0, width]);
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.y_pos
})]).range([height, 0]);
var svg = d3.select("#box")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// create group
var group = svg.append("g")
.attr("class", "main_group")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// bind the data
var boxes = group.selectAll("boxes")
.data(data)
.enter();
// add rects
boxes.append("rect")
.attr("class", "boxes")
.attr("x", function(d) {
return d.x_pos
})
.attr("y", function(d) {
return d.y_pos
})
.attr("rx", "5px")
.attr("width", 60)
.attr("height", 20)
.attr("stroke", "darkgray")
.attr("fill", "lightblue");
// add text
boxes.append("text")
.attr("class", "legend_text")
.attr("x", function(d) {
return d.x_pos
})
.attr("y", function(d) {
return d.y_pos
})
.attr("dx", "0.5em")
.attr("dy", "1.0em")
.style("font-weight", "bold")
.text(function(d) {
return d.name;
});
// add text coordinates
boxes.append("text")
.attr("class", "legend_text")
.attr("x", function(d) {
return d.x_pos
})
.attr("y", function(d) {
return d.y_pos
})
.attr("dx", "-2.5em")
.attr("dy", "-.5em")
.style("font-weight", "bold")
.text(function(d) {
return "(" + d.x_pos + ", " + d.y_pos + ")";
});
</script>

这里的问题很简单:您没有使用任何比例来定位矩形:

.attr("x", function(d) {
return d.x_pos
})

解决方案:使用秤。

.attr("x", function(d) {
return x(d.x_pos)
//     ^--- scale here
})

此外,您没有正确设置域。它应该是:

var x = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x_pos
})]).range([0, width]);

以下是包含这些更改的代码:

svg {
border: 2px solid gray;
}
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="box">
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
data = [{
"x_pos": "100",
"y_pos": "400",
"name": "Aa"
},
{
"x_pos": "200",
"y_pos": "200",
"name": "Bb"
},
{
"x_pos": "300",
"y_pos": "100",
"name": "Cc"
},
{
// "x_pos": "300",
"x_pos": "525",
"y_pos": "300",
"name": "Dd"
},
{
"x_pos": "0",
"y_pos": "0",
"name": "Ee"
}
]
data.forEach(function(d) {
d.x_pos = +d.x_pos;
d.y_pos = +d.y_pos;
});
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = 600 - margin.left - margin.right, // width=500
height = 600 - margin.top - margin.bottom; // height=500
var x = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x_pos
})]).range([0, width]);
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.y_pos
})]).range([height, 0]);
var svg = d3.select("#box")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// create group
var group = svg.append("g")
.attr("class", "main_group")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// bind the data
var boxes = group.selectAll("boxes")
.data(data)
.enter();
// add rects
boxes.append("rect")
.attr("class", "boxes")
.attr("x", function(d) {
return x(d.x_pos)
})
.attr("y", function(d) {
return y(d.y_pos)
})
.attr("rx", "5px")
.attr("width", 60)
.attr("height", 20)
.attr("stroke", "darkgray")
.attr("fill", "lightblue");
// add text
boxes.append("text")
.attr("class", "legend_text")
.attr("x", function(d) {
return x(d.x_pos)
})
.attr("y", function(d) {
return y(d.y_pos)
})
.attr("dx", "0.5em")
.attr("dy", "1.0em")
.style("font-weight", "bold")
.text(function(d) {
return d.name;
});
// add text coordinates
boxes.append("text")
.attr("class", "legend_text")
.attr("x", function(d) {
return x(d.x_pos)
})
.attr("y", function(d) {
return y(d.y_pos)
})
.attr("dx", "-2.5em")
.attr("dy", "-.5em")
.style("font-weight", "bold")
.text(function(d) {
return "(" + d.x_pos + ", " + d.y_pos + ")";
});
</script>

最新更新