I get pretty excited about the D3.js studying and presentation. And I get stuck on the data importing part. I've tried one month now, and couldn't find a solution for it.
If the data is simply pasted in the code, the scripts works perfectly fine. But once I tried to import the data from outside the script. The webpage won't show anything.
Can someone be kind enough to give me a hand?
Here are my scripts and data:
Working version:
<!DOCTYPE html>
<html>
<head>
<charset=utf-8">
<title>Successful Data Comination In Bar Chart</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
var dataset = [{"name":"AAA", "age":10},{"name":"BBB", "age":20},{"name":"CCC", "age":30}];
var canvas = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500);
canvas.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("width", function (d) { return d.age*10; })
.attr("height", 48)
.attr("y", function (d,i) { return i*50; })
.attr("fill", "gray");
canvas.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("fill", "white")
.attr("x", 2)
.attr("y", function (d,i) { return i*50 +27; })
.text(function (d) { return d.name + " " + d.age; });
</script>
</body>
</html>
Not working version:
<!DOCTYPE html>
<html>
<head>
<charset=utf-8">
<title>Testing Pie Chart</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
var dataset = [];
d3.json("mydata.json", function(data) {
dataset = data;
var canvas = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500);
canvas.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("width", function (d) { return d.age*10; })
.attr("height", 48)
.attr("y", function (d,i) { return i*50; })
.attr("fill", "gray");
canvas.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("fill", "white")
.attr("x", 2)
.attr("y", function (d,i) { return i*50 +27; })
.text(function (d) { return d.name + " " + d.age; });
});
</script>
</body>
</html>
The json data named "mydata.json" is like:
[
{"name": "AAA", "age": 10},
{"name": "BBB", "age": 20},
{"name": "CCC", "age": 30}
]
I am new to Stackoverflow, and trying to edit it as I want, but not perfect. Please feel free to let me know if you get confused about the codes. I will explain, cause I really want to solve this. Thanks a lot!
Thanks for tipping me off! Looking forward to your reply keenly!
This is a security feature in browsers known as the same-origin policy. You can view this in action by firing up your browser-of-choice's dev tools and seeing what happens when it tries to fetch your JSON file.
There are various methods to work around this. If you have access to web hosting, throw it up there. Otherwise, choose a method to run a lightweight server locally. The simplest one that people are routinely told is to serve an index.html file in python:
#(in v2.x)
python -m SimpleHTTPServer 8000
#(in v3.x)
python -m http.server 8000
then browsing to localhost:8000. This is explained in slightly more detail on the d3 wiki. For more in-depth explanations and whatnot, I recommend some reading.
Related
I'm learning d3.js, and I'm trying to create a bar chart from a .csv file (names of students and their grades). I wrote the code below, but it doesn't generate any bar chart, and I can't understand why. Can you help, please? Thank you!
Here's my .csv file:
Name,Grade
John,95
Jennifer,96
Hank,100
Christina,98
Paul,88
Amy,76
Raul,72
Samantha,70
Sean,68
Abby,90
Sally,85
<script type="text/javascript">
d3.csv("votiOne.csv", function(data) {
var canvas = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);
canvas.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("width", function (d) { return d.Grade; })
.attr("height", 50)
.attr("y", function (d, i) { return i * 50; })
.attr("fill", "blue");
})
</script>
It works depending on the d3 version you are using:
For d3 version 4, the code should work:
...
<script src="https://d3js.org/d3.v4.min.js"></script>
...
d3.csv("votiOne.csv", function(data) {
...
For d3 version 5, the code is using a Promise (see also this SO Question) and looks like this:
...
<script src="https://d3js.org/d3.v5.min.js"></script>
...
d3.csv("votiOne.csv").then(function(data) {
...
Full working examples:
d3js v4 example
d3js v5 example
I'm brand new to D3.js, so my apologies in advance if I'm overlooking something obvious, but I cannot for the life of me figure out what's not working here...
I've been inching my way through Scott Murray's Interactive Data Visualization for the Web and I've hit a block at Chapter 7. My goal is to load some simple data from a csv document, parse the first column as Date data, and then display. The head of the csv looks like this...
Date, Amount
9/15/17, 26
11/9/17, 31
11/30/17, 23
12/21/17, 26
2/7/18, 23
I run the code below (which comes directly from the book!) and...none of that seems to be happening. When I enter "dataset" into the console, it only seems to include the final row:
{Date: "01/31/17", Amount: "23"}
Amount: "23"
Date: "01/31/17"
I'm perplexed since, again, the code itself comes from the book. I've been working through previous chapters just fine until now. And yes, I'm running a local server. Any idea what I'm doing wrong here? Thanks very much in advance!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Time scale</title>
<script type="text/javascript" src="../d3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
var padding = 40;
var dataset, xScale, yScale;
//For converting strings to Dates
var parseTime = d3.timeParse("%m/%d/%y");
//Function for converting CSV values from strings to Dates and numbers
var rowConverter = function(d) {
return {
Date: parseTime(d.Date),
Amount: parseInt(d.Amount)
};
}
//Load in the data
d3.csv("time_scale_data.csv", rowConverter, function(data) {
//Copy data into global dataset
dataset = data;
//Create scale functions
xScale = d3.scaleTime()
.domain([
d3.min(dataset, function(d) { return d.Date; }),
d3.max(dataset, function(d) { return d.Date; })
])
.range([padding, w - padding]);
yScale = d3.scaleLinear()
.domain([
d3.min(dataset, function(d) { return d.Amount; }),
d3.max(dataset, function(d) { return d.Amount; })
])
.range([h - padding, padding]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Generate date labels first, so they are in back
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return formatTime(d.Date);
})
.attr("x", function(d) {
return xScale(d.Date) + 4;
})
.attr("y", function(d) {
return yScale(d.Amount) + 4;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "#bbb");
//Generate circles last, so they appear in front
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.Date);
})
.attr("cy", function(d) {
return yScale(d.Amount);
})
.attr("r", 2);
});
</script>
</body>
</html>
Instead of :
d3.csv("time_scale_data.csv", rowConverter, function(data) {
--- your code ---
});
Try this :
d3.csv("time_scale_data.csv", rowConverter).then(data){
--- your code ---
});
Today I am learning about D3.js
I started by studying this content:
https://bost.ocks.org/mike/circles/
Most of it seems easy to understand and follow.
But I have a problem getting exit() to work.
I do understand the idea that I can use exit() to force elements in my DOM to synch with values in a JS array.
So I wrote some code to demonstrate this idea and my code fails.
I want to know how I can rewrite my JS so that exit() will force elements in my DOM to synch with values in a JS array.
<html>
<body>
Ref:
<a href='https://bost.ocks.org/mike/circles/' target='x'>
https://bost.ocks.org/mike/circles/
</a>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
// I should create 3 circles
var svg1 = d3.select('body')
.append('svg')
.attr('id','svg1')
.attr('width',800).selectAll("circle")
.data([0, 1, 2])
.enter()
.append("circle")
.attr("cy", 60)
.attr("cx", function(d, i) { return i * 100 + 30 })
.attr("r", function(d) { return 5+5*d })
// So far so good. I see 3 circles
// Now I should remove some.
var mycircles_a = svg1.selectAll("circle")
.data([99, 88])
// I should ask D3 to make the data-array sync with the circle-elements:
mycircles_a.exit().remove()
// Above call fails for some reason; I still see 3 circles!
// I should see 2 circles because mycircles_a is bound to an array with only 2 values.
'bye'
</script>
</body>
</html>
In your example svg1 is, itself, an "enter" selection.
Your code works just fine if you break the chain, making svg1 just a selection that creates the SVG:
var svg1 = d3.select('body')
.append('svg')
.attr('id','svg1')
.attr('width',800);
svg1.selectAll("circle")
.data([0, 1, 2])
.enter()
.append("circle")
.attr("cy", 60)
.attr("cx", function(d, i) { return i * 100 + 30 })
.attr("r", function(d) { return 5+5*d })
var mycircles_a = svg1.selectAll("circle")
.data([99, 88])
mycircles_a.exit().remove()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
You're not saving a reference to svg1 correctly.
https://jsfiddle.net/y008c61L/
var svg1 = d3.select('body')
.append('svg')
.attr('id','svg1')
.attr('width',800);
svg1.selectAll("circle")
//...
I know that the question has been largely covered but I am still stuck with it so any help is more than appreciated.
I am trying to display some data from a csv file locally on my computer in d3.js script but nothing is displayed. I have tried two solutions so far:
Solution 1:
Some of the answers found online state that the solution is to install a local server. So I installed a portable version of Uniform Server UPX (because I don't have the administrator privileges to install node http server on my computer).
But even when I run the server from the directory where my index.html is located, nothing happens. Here is the code I am using for reading data from the csv file:
d3.csv("data.csv", type, function(error, data) {
x.domain([0, d3.max(data, function(d) { return d.value; })]);
chart.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", function(d) { return x(d.value); })
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) { return x(d.value) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d.value; });
});
Furthermore, this solution isn't convenient for me because I want the data to be updated automatically from the csv file without having to run a cmd prompt to start the http server...
Solution2
I tried to allow the browser access local files by adding the following line in my head index, without success either:
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<meta http-equiv="Access-Control-Allow-Origin" content="*"/>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<style>
Could you please point out what I should do to solve the problem?
Thanks.
I am a beginner with D3 and JS in general.
I am trying to do a simple rectangle visualisation with a small csv file as a source.
price, units
80.67, 100
80.87, 99
79.34, 47
File, csv are in the same folder.
I am using Python's SimpleHTTPServer to serve locally in this folder.
This is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test Data</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
</head>
<body>
<script type="text/javascript">
// load csv from the same directory
d3.csv("test.csv", function (data){
return {
price: +data.price, // convert to number with +
units: +data.units, // convert to number with +
};
var canvas = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500)
canvas.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("width", function (d) { return d.price; })
.attr("height", 48)
.attr("y", function (d) { return d.units; })
.attr("fill", "blue");
canvas.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("fill", "white")
.attr("y", function (d) { return d.units + 24; })
.text( function (d) { return d.units;})
});
</script>
</body>
I am getting no errors, just a blank page.
What is wrong with this code?
The first thing you do in your callback is to return. None of the code after that is being executed. I'm referring to
return {
price: +data.price, // convert to number with +
units: +data.units, // convert to number with +
};
which should probably be
data.forEach(function(d) {
d.price = +d.price;
d.units = +d.units;
});
The signature of the callback should also be function(error, data) instead of function(data).