问题
I am trying to generate a graph based on some data from a CSV file.
My code:
<script>
var svg = d3.select("body").append("svg")
.attr("width", 1000)
.attr("height", 1000);
function render(data){
var circles = svg.selectAll("circle").data(data);
circles.enter().append("circle")
.attr("r", 1);
circles
.attr("cx", function (d){return d[' Monthly Term']})
.attr("cy", function (d){ return d[' Principal Balance']/1000});
circles.exit().remove();
}
d3.csv("{% static "data/Total.csv" %}" , type, function(myArray){
render(myArray);
myArray.forEach(function(d){
console.log(d[' Principal Payment'] + ", " + d[' Interest Payment'] + ", " + d[' Principal Balance'] + ", " +d[' Monthly Term']);
});
});
function type(d){
d.value = +d.value;
return d;
}
</script>
Everything "works" but the Y-axis seems reversed.
Not sure if you guys can see the inspection window but the Y-value should be decreasing as x value increases.
Any ideas?
回答1:
In your console output, the Y value is decreasing as X value increases. In an SVG, the 0,0 location is top left. So a lower Y value is closer to the top of the screen. Try inverting the Y value:
.attr("cy", function (d){ return height - d[' Principal Balance']/1000});
回答2:
As @genestd states in his answer, SVG y coordinates start at the top and increase in value moving down. Generally, you should be using a d3 scale to map your user space values to svg coordinate values. Looking at the classic bar chart example, you see these lines:
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
Here, the x scale goes from 0 to width and the y from height to 0. They are reversed from each other because of the very thing you are seeing, x increases going left to right while y increases going top to bottom. This .range
call is mapping the SVG coordinates.
Later you'll see this line:
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
This part has now mapped the user space coordinates, saying they run from 0 to the maximum of our data.
You can then use the scales as functions when you plot your point.
In your code it might look like this:
var svg = d3.select("body").append("svg")
.attr("width", 1000)
.attr("height", 1000);
var x = d3.scaleLinear().range([0, 1000]),
y = d3.scaleLinear().range([1000, 0]);
function render(data){
x.domain([0, d3.max(data, function(d){
return d[' Monthly Term'];
});
y.domain([0, d3.max(data, function(d){
return d[' Principal Balance']/1000;
});
var circles = svg.selectAll("circle").data(data);
circles.enter().append("circle")
.attr("r", 1);
circles
.attr("cx", function (d){return x(d[' Monthly Term']); })
.attr("cy", function (d){ return y(d[' Principal Balance']/1000); });
...
来源:https://stackoverflow.com/questions/44834747/d3-y-axis-seems-inverted