Reputation: 67
For a school project, I have to create a graph using a JSON file with input data. Using d3.scaleLinear() and using my x and y values as input, I am trying to get my graph to scale so all of my points will be graphed. Without using a JSON file and using a simple var data = [[20, 5]] and scaling by using d[0] and d[1] where d.x and d.y are works. But I can't figure out how to get it to work by using a JSON file as the input data.
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#scatter-chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
//Read the data
d3.json("test_points.json", function(data) {
// Add X axis
var x = d3.scaleLinear()
.domain([0, d3.max(data, function (d) {
return d.x;
})])
.range([0, width])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function (d) {
return d.y;
})])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// Add dots
svg.append('g')
.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("cx", function (d) { return x(d.x); } )
.attr("cy", function (d) { return y(d.y); } )
.attr("r", 6)
.style("fill", "#ff0084")
})
</script>
using test_points.json in a sperate file
[
{"x":"11","y":"14"},
{"x":"5","y":"17"},
{"x":"7","y":"19"},
{"x":"1","y":"7"},
{"x":"27","y":"3"},
{"x":"5","y":"0"},
{"x":"9","y":"4"},
{"x":"13","y":"1"},
{"x":"17","y":"20"},
{"x":"19","y":"16"},
{"x":"12","y":"1"},
{"x":"11","y":"9"},
{"x":"1","y":"7"},
{"x":"0","y":"4"}
]
Upvotes: 1
Views: 241
Reputation: 102194
Your first title actually contains the hint to fix your code (I rolled back your edit).
When you say "my d3.scaleLinear function won't scale past 9" it becomes clear that you're using the JSON values as strings, not as numbers (unlike your hardcoded var data
, which contain numbers). The thing is that strings behave differently than numbers:
console.log("9" > "8000000")
As you can see, when comparing strings nine seems to be bigger than eight million... what's actually happening here is that strings are compared letter by letter, and so "9"
is bigger than "8"
.
The solution is just converting the strings to numbers:
data.forEach(function(d) {
d.x = +d.x;
d.y = +d.y;
});
Here is your original code:
// set the dimensions and margins of the graph
var margin = {
top: 10,
right: 30,
bottom: 30,
left: 60
},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var data = [{
"x": "11",
"y": "14"
},
{
"x": "5",
"y": "17"
},
{
"x": "7",
"y": "19"
},
{
"x": "1",
"y": "7"
},
{
"x": "27",
"y": "3"
},
{
"x": "5",
"y": "0"
},
{
"x": "9",
"y": "4"
},
{
"x": "13",
"y": "1"
},
{
"x": "17",
"y": "20"
},
{
"x": "19",
"y": "16"
},
{
"x": "12",
"y": "1"
},
{
"x": "11",
"y": "9"
},
{
"x": "1",
"y": "7"
},
{
"x": "0",
"y": "4"
}
];
// Add X axis
var x = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x;
})])
.range([0, width])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.y;
})])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// Add dots
svg.append('g')
.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x(d.x);
})
.attr("cy", function(d) {
return y(d.y);
})
.attr("r", 6)
.style("fill", "#ff0084")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
And here is the same code using numbers instead of strings:
// set the dimensions and margins of the graph
var margin = {
top: 10,
right: 30,
bottom: 30,
left: 60
},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var data = [{
"x": "11",
"y": "14"
},
{
"x": "5",
"y": "17"
},
{
"x": "7",
"y": "19"
},
{
"x": "1",
"y": "7"
},
{
"x": "27",
"y": "3"
},
{
"x": "5",
"y": "0"
},
{
"x": "9",
"y": "4"
},
{
"x": "13",
"y": "1"
},
{
"x": "17",
"y": "20"
},
{
"x": "19",
"y": "16"
},
{
"x": "12",
"y": "1"
},
{
"x": "11",
"y": "9"
},
{
"x": "1",
"y": "7"
},
{
"x": "0",
"y": "4"
}
];
data.forEach(function(d) {
d.x = +d.x;
d.y = +d.y;
});
// Add X axis
var x = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x;
})])
.range([0, width])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.y;
})])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// Add dots
svg.append('g')
.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x(d.x);
})
.attr("cy", function(d) {
return y(d.y);
})
.attr("r", 6)
.style("fill", "#ff0084")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
Upvotes: 1