Hi all I've just started with Javascript and i wanted to use d3 and I already met into a problem:
XMLHttpRequest cannot load https://blahblah/api/votes. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.
This problem was shown in my console.
Attached is my code:
<!DOCTYPE html>
<html>
<head>
<title>Testbed!</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript"></script>
</head>
<body>
<script>
d3.select("body").append("p").text("hi, whats up");
console.log(d3);
d3.json("https://blahblah/api/votes", function(data) {
var canvas = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500)
canvas.selectAll("rect")
.data(data) //the data in the bracket is because our function uses the varible data
.enter()
.append("rect")
.attr("width", function(d) { return d; })
.attr("height", 50)
.attr("y", function(d,i) { return i*10; })
.attr("fill", "blue");
canvas.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("fill", "white")
.attr("y", function(d,i) { return i*50; })
.text(function (d) { return d.document_id + 25; })
})
</script>
</body>
</html>
Can someone give me some clues as to what is going on?
Related
I'm trying to make a choropleth map using d3.js where each of the map's paths has a tooltip that pops up upon mouseover. I would like the tooltip to include information related to the path (in this case that information would be a rating for the given district).
The code I'm using below works well with the exception that the tooltip is stuck on the first row of the input csv. For example, if I hover over District 1 the tooltip will correctly display the district's rating. When I hover over District 2 it still only shows the data for District 1. This occurs even if the first district I hover over is a district besides District 1. In other words, the tooltip is stuck on District 1 indefinitely.
What am I missing here? Thanks for your advice in advance.
Here's a sample of the ratings.csv data:
"District","Rating"
"1","Hot"
"2","Cold"
"3","Cold"
"4","Hot"
And here's a sample of the topojson:
"objects":{"districts":{"type":"GeometryCollection","geometries":[{"arcs":[[0,1,2]],"type":"Polygon","properties":{"District":"1"}}
And here's the html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/topojson#3"></script>
</head>
<body>
<div class="map-div">
<script type="text/javascript">
var width = 500;
var height = 700;
var map = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
Promise.all([
d3.json("districts.json"),
d3.csv("ratings.csv", function(d) {
return {
District: d.District,
Rating: d.Rating
}
})
])
.then(function(data){
console.log(data)
var conus = topojson.feature(data[0], {
type:"GeometryCollection",
geometries: data[0].objects.districts.geometries
});
var projection = d3.geoConicConformal()
.parallels([38 + 20 / 60, 39 + 50 / 60])
.rotate([122, 0])
.fitExtent([[0,0],[630,700]], conus);
var path = d3.geoPath()
.projection(projection);
var ratings_map = d3.map()
data[1].forEach(function(d){
ratings_map.set(d["District"],
{"Rating" : d["Rating"]});
});
var colorScale = d3.scaleOrdinal()
.domain(["Cold", "Hot"])
.range(["#11ede9", "#ed4011"]);
map.selectAll("path")
.data(topojson.feature(data[0], data[0].objects.districts).features)
.enter()
.append("path")
.attr("d", path)
.attr("class", "map-border")
.on("mouseover", function(d) {
d3.selectAll("path")
.style("opacity", .5)
d3.select(this)
.style("cursor", "pointer")
.style("opacity", 1)
.style("stroke-width", "3px")
.style("stroke", "black")
.raise();
})
.on('mousemove', function (d) {
tooltip.style("visibility", "visible")
.style("left", (d3.event.pageX - 550) + "px")
.style("top", (d3.event.pageY - 8) + "px")
.data(data[1])
.text(function(d) {
console.log(d)
return d.Rating
})
tooltip.transition()
.duration(0)
.style("opacity", 1);
})
.on("mouseout", function(d) {
tooltip.transition()
.style("visibility", "hidden");
d3.selectAll("path")
.style("opacity", 1)
d3.select(this)
.style("stroke-width", "0.75px")
.style("stroke", "white")
.style("opacity", 1)
.style("cursor", "default")
.attr("fill", function() {
let district = ratings_map.get(d.properties.DISTRICT);
return colorScale(district["Rating"]);
});
})
.attr("fill", function(d){
let district = ratings_map.get(d.properties.DISTRICT);
return colorScale(district["Rating"]);
});
});
</script>
</div>
</body>
</html>
I'm trying to load a csv file with x and y coordinates and create circles with that coordinates. I've understood how to load a csv file and i can log coordinates in the console but I don't understand why the log function return Not_a_number when i try to create circles. Is there a problem with mine data.map function? Thanks
Here the code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 900;
var h = 500;
var padding = 20;
var dataset = [];
d3.csv("dataset.csv", function(data) {
dataset = data.map(function(d,i) {
//THIS WORKS
console.log(d);
console.log(i);
return [ +d["x-coordinate"], +d["y-coordinate"]
]; });
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
//THIS DOESNT WORK
console.log(d);
return d[0];
})
.attr("cy", function(d) {
return d[1];
})
.attr("r", function(d) {
return d[1];
})
});
</script>
</body>
</html>
You can only access the dataset after it has been asynchronously loaded inside d3.csv.
The code inside d3.csv is executed asynchronously, meaning it would run only after the file has been loaded, it is not guaranteed to run before the code below it.
d3.csv("dataset.csv", function(data) {
dataset = data.map(function(d,i) {
//THIS WORKS
console.log(d);
console.log(i);
return [ +d["x-coordinate"], +d["y-coordinate"]
]; });
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
//THIS DOESNT WORK
console.log(d);
return d[0];
})
.attr("cy", function(d) {
return d[1];
})
.attr("r", function(d) {
return d[1];
})
.text("hello world");
});
Alternatively, create a method and pass dataset into that method inside d3.csv.
The following is my code. Yet when I run it I get a blank page. Why is this the case ? Also how can I use data from hundreds of columns to make a simple interactive visual using d3 ? I would like to add that the following csv file "LoanStats3a.csv" is in the same folder.
<html>
<title>Loans</title>
<link href="../css/jquery-ui.css" rel="stylesheet" />
<script src="../Scripts/jquery-1.12.4"></script>
<script src="../Scripts/jquery-1.12.4.js"></script>
<script src="../Scripts/jquery-ui.js"></script>
<script src="http://d3js.org/d3.v3.js" charset="utf-8"></script>
<style>
#LoanStats3a{
color: blueviolet;
}
</style>
<body>
<script>
d3.csv("LoanStats3a", function (file1){
var bg = d3.select("body").append("svg")
.attr("width", 5000)
.attr("height", 5000);
bg.selectAll("rect")
.data(file1)
.enter()
.attr("width", function(d){return d.loan_amnt / 100;})
.attr("height", function(d) {return d.term;})
.attr("y", function (d,i) {return i *50;})
.attr("fill", function (d){"red","blue";});
}
</script>
</body>
This is because after binding the data to your empty selection, you have to append a rect element for each data.
Also, your attribute "fill" is incorrect.
bg.selectAll("rect")
.data(file1)
.enter()
.append("rect") // <= You need to create a rect for each data
.attr("width", function(d){return d.loan_amnt / 100;})
.attr("height", function(d) {return d.term;})
.attr("y", function (d,i) {return i *50;})
.attr("fill", "blue");
If you want to change the color depending on the data, create a function and return something.
// For example
.attr("fill", function(d){return d.loan_amnt > 25000 ? "blue" : "red"});
Here's a JsFiddle with random data : DEMO
EDIT : If it's still not working, it's probably a problem with your data because the only thing different between our code is that I used custom data in the JsFiddle.
I notice that your csv file doesn't have the extension .csv, it's just LoanStats3a ?
You should do a console.log(file1), to check if your data are correct.
Take a look at D3 CSV for how to load a csv file.
You are missing a closing ) at the end:
.attr("fill", function (d){"red","blue";});
}
// ^ Here should be a )
</script>
It helps if you have proper indent:
<script>
d3.csv("LoanStats3a", function(file1) {
var bg = d3.select("body").append("svg")
.attr("width", 5000)
.attr("height", 5000);
bg.selectAll("rect")
.data(file1)
.enter()
.attr("width", function(d) {
return d.loan_amnt / 100;
})
.attr("height", function(d) {
return d.term;
})
.attr("y", function(d, i) {
return i * 50;
})
.attr("fill", function(d) {
"red", "blue"; // What is going on here?
// Did you for to return?
// return "blue";
});
});
</script>
I am using D3.js to draw some circles inside a div but for some reason no data is displayed in the bottom third of the did even though the specified size of the canvas is equivalent to the size of the of the div.
var data = d3.csv('circles.csv', function(data){
var canvas = d3.select('.cell').append("svg");
canvas.selectAll("circles")
.attr("width", 300)
.attr("height", 250)
.data(data)
.enter()
.append("circle")
.attr("cx", function(d){return (+d.x)})
.attr("cy", function(d){return (+d.y)})
.attr("r", function(d){return (+d.radius)})
.attr("fill", "green");
});
I set a code snippet for what it looks like if no svg size specified. So if ur case is like this, the data point at the bottom may be just go out the SVG viewport area.
var canvas = d3.select('.cell').append("svg")
// if u did not specify size
//.attr("width", 400).attr("height", 400);
canvas.selectAll("circle").data([0])
// .attr("width", 300)
// .attr("height", 250)
// .data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return 150;
})
.attr("cy", function(d) {
return 125;
})
.attr("r", function(d) {
return 125;
})
.style("fill", "green");
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
</head>
<body>
<div class="cell" style="width:500px; height:500px;"></div>
</body>
</html>
I get a blank screen when the browser tries to render the following code and its json file. happens both Safari and Chrome. Seems like it renders the SVG in the canvas but not the rest. Am I missing something in the structure? Or should it be run on a server ?
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
// load the external data from built-in method in D3
d3.json("datastuff.json", function(data) {
// after data load then...
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.age * 10; })
.attr("height", 50)
.attr("y", function (d,i) {return i * 50; })
.attr("fill", "blue")
})
</script>
</body>
</html>
Here is its associated external datastuff.json file.
[
{“name”:”Maria”,”age”:30},
{“name”:”Fred”,”age”:50},
{“name”:”Francis”,”age”:12}
]