I want to write a code snippet in d3js that will read a json file, and display a simple bar chart based on the contents of the json file. My json file, mydata.json, is:
[
{“name”: “Apollo_Diomedes”, “age”: 300},
{“name”: “Bjorn_the_Fellhanded”, “age”: 900},
{“name”: “Jonah_Orion”, “age”: 500}
]
d3js code snippet, from index.html:
<body>
<script>
d3.json("mydata.json", 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(x) { return x.age; })
.attr("height", 45)
.attr("y", function(x, i) { return i * 50; })
.attr("fill", "blue")
});
</script>
</body>
I'm using d3 v4:
<script src="http://d3js.org/d3.v4.js"></script>.
I've tried opening the index.html file directly, and opening a local server and navigating to localhost:8080 as directed here; both just show me a blank screen. Both index.html and mydata.json are saved in the same folder on my desktop.
For those interested, it's actually this slightly outdated youtube tutorial; it runs d3 v3.
P.S. I can read in info from a CSV, but not json.
It sounds like you have problems with parsing the JSON data. Try replacing your quotation marks to the English ones (").
And in general, always check the console log of your Web browser. I am certain that you will some error printed there.
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
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 try to display round images in a svg. The purpose of it is to display round profile pictures within a graph (like in Gmail). The square images of the people are stored in a spritesheet (profiles.png) and I use d3.js for dynamically generating the svg.
This is the part of the code for the round images
var imgurl = '../../../images/profiles.png';
var svggraph = d3.select("#graph")
.append("svg:svg")
.attr("width", 300)
.attr("height", 300);
var imgRadius = 40;
var profilePos = 1;
var numProfiles = 3;
svggraph.append("defs")
.append("pattern")
.attr("id", "patternId")
.attr("height", 1)
.attr("width", 1)
.attr("x", "0")
.attr("y", "0").append("svg:image")
.attr("xlink:href", imgurl)
.attr("x", -profilePos*2*imgRadius)
.attr("y", 0)
.attr("width", numProfiles*2*imgRadius)
.attr("height", 2*imgRadius);
svggraph.append("circle")
.attr("r", imgRadius)
.attr("cx", imgRadius)
.attr("cy", imgRadius)
.attr("fill", "url(#patternId)");
// to test the imgurl
svggraph.append("svg:image")
.attr("id", "testImage")
.attr("xlink:href", imgurl)
.attr("x", 0)
.attr("y", 100)
.attr("width", 150)
.attr("height", 50);
It worked when I tested it in a plain test HTML, it also worked when I integrated it in my Joomla component in Firefox and Chrome. But if there is a GET query in the url (basically as soon as there is a ? even with no parameters), the round image is not displayed anymore. The svg tags in the "live source code" in the developer tools looks the same if there is a "?" in the url or not. It is always displays correct (with or without query url) in Chrome.
So in summary:
in Chrome -> always works
in FF "plain" HTML with and without ? in url -> works
in FF within Joomla without ? in url -> works
in FF within Joomla with ? in url -> round image not displayed
The test image (#testImage) is always displayed, so the url to the image is apperently correct.
I also tried the same but with clipPath instead of using a pattern, with the same result (not displayed in FF if ? in url and Joomla).
I already did an extensive google search, but the best I could find was this post with the same problem but not an solution.
https://forum.joomla.org/viewtopic.php?t=912784
I don't know what else I could try to fix this.
I had the same issue happening to me for my Joomla 3.6.4 site in Firefox. I resolved it by removing the <base> tag from my template. I added this code to my index.php file in my template:
$doc = JFactory::getDocument();
unset($doc->base);
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 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.