I am running this below simple code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;1
var h = 300;
//Define default path generator
var path = d3.geo.path();
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Load in GeoJSON data
d3.json("india.json", function(error,json) {
console.log(json);
//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path);
});
</script>
</body>
</html>
When i run it, i am getting the blank web page without any error. india.json file is a valid json file, i verified it in http://jsonlint.com/
I am new to javascript. Any help would be greatly appreciated.
Thanks,
Finally, after many trails, i found the solution an it was problem with projection, so i have used the below code and it worked.
//Width and height
var w = 960
var h = 1000
//Define map projection
var projection = d3.geo.mercator()
.translate([w/2,h/2])
.scale(5000);
//Define path generator
var path = d3.geo.path()
.projection(projection);
Related
Trying to layer a geo-heatmap using simpleheat.js and D3.
Working off an example (https://bl.ocks.org/patricksurry/803a131d4c34fde54b9fbb074341daa5). I am Successful at drawing the map but not the points as heatmap. No error on console.log.
I get one rainbow colored blob (I overdid the radius) on the upper left corner next to the map.
Could not find many examples and documentation on simpleheat is scant. Would appreciate any insight into this.
Thank you.
<!DOCTYPE html>
<html>
<head>
<style>
#container svg, #container canvas {
position: absolute;
top: 0;
}
</style>
<meta charset="utf-8">
<title>D3 Map Example</title>
</head>
<body>
<div id= "container">
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src = "node_modules/simpleheat/simpleheat.js"></script>
<script>
//Width and height
var w = 960;
var h = 600;
div = d3.select("#container")
mapLayer = div.append('svg')
.attr("id","map")
.attr("width",w)
.attr("height",h)
canvasLayer = div.append('canvas').attr('id', 'heatmap').attr('width', w).attr('height', h);
var canvas = canvasLayer.node(),
context = canvas.getContext("2d");
//Define map projection
var projection = d3.geoMercator()
.center([ -120, 37 ])
.translate([ w/2, h/2 ])
.scale([ 2600 ]);
//Define path generator
var path = d3.geoPath()
.projection(projection)
var svg = d3.select("#container")
.append("svg")
.attr("width", w)
.attr("height", h);
// read data in
d3.queue()
.defer(d3.json,"ca.json")
.defer(d3.csv, "heatCAN.csv")
.await(main)
function main (err, ca, heatCAN) {
console.log(heatCAN)
mapLayer
.append('svg')
.selectAll("path")
.data(ca.features)
.enter()
.append("path")
.attr("d",path)
.attr("stroke","#000000")
.attr("fill","#ffffff")
//add heatmap
simpleheat(canvas).data(heatCAN.map(x=>[x.LON,x.LAT,x.cMort_90d])).radius(100,100).draw(0.05);
}
</script>
</body>
</html>
I'm working on a very basic bar plot with dimple.js. When I render in the browser, it shows only the axes and axis labels, but no bars. Any help appreciated. I am using python to create a localhost.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="main.css" rel="stylesheet">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.0.0.min.js"></script>
</head>
<body>
<h2> Rise of the Machines: R&D on Unmanned Aerial Aircrafts</h2>
<script src="index.js"></script>
</body>
</html>
index.js
function draw(data) {
/*
D3.js setup code
*/
var margin = 75;
var width = 1400 - margin;
var height = 600 - margin;
/* Find body tag, append svg, and add chart group tag*/
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin)
.attr("height", height + margin)
.append("g")
.attr("class","chart");
/*
Dimple.js Chart construction code
*/
var myChart = new dimple.chart(svg, data);
x = myChart.addCategoryAxis("x", "");
y = myChart.addMeasureAxis("y", "Share of Global Spending (%)");
myChart.addSeries(null, dimple.plot.bar);
myChart.draw();
};
d3.csv("data.csv", draw);
You'd not tell to dimple where to get the data:
x = myChart.addCategoryAxis("x", ""); //<---- X values
y = myChart.addMeasureAxis("y", "Share of Global Spending (%)"); // <--- Y values
example
var data = [
{ "Word":"Hello", "Awesomeness":2000 },
{ "Word":"World", "Awesomeness":3000 }
];
chart.addCategoryAxis("x", "Word");
chart.addMeasureAxis("y", "Awesomeness");
another example
var data = [
{ "data1":"Hello", "data2":2000 },
{ "data1":"World", "data2":3000 }
];
chart.addCategoryAxis("x", "data1");
chart.addMeasureAxis("y", "data2");
You must point to data origin, from csv column name. With your csv:
Xdata, Yvalue
1,10
2,20
3,30
4,20
Your code:
chart.addCategoryAxis("x", "Xdata");
chart.addMeasureAxis("y", "Yvalue");
On the dimple website, it seems to be recommended procedure to use .tsv (tab seperated values) as opposed to comma seperated values.
Here is a sample (vertical) bar chart code taken from the site
<html>
<div id="chartContainer">
<script src="/lib/d3.v3.4.8.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.2.0.min.js"></script>
<script type="text/javascript">
var svg = dimple.newSvg("#chartContainer", 590, 400);
d3.tsv("/data/example_data.tsv", function (data) {
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 510, 330)
myChart.addCategoryAxis("x", ["Price Tier", "Channel"]);
myChart.addMeasureAxis("y", "Unit Sales");
myChart.addSeries("Channel", dimple.plot.bar);
myChart.addLegend(65, 10, 510, 20, "right");
myChart.draw();
});
</script>
</div>
</html>
Hopefully, this will guide you in the right direction.
I am trying to draw a huge (60k) number of (x, y) points on an HTML5 canvas and simulate streaming data points with D3.js in Chrome and Firefox, and finding that the browser freezes and crashes after about 10 seconds.
I am generating the data set with random values as follows:
var data = d3.range(60000).map(function() { return Math.random() * 500; });
Would it help to break generation of data into sections? I feel that this might be caused by trying to store such a large data set at one time as I have shown.
Is there any way that I can prevent this from happening? Such as drawing and saving smaller sections as tiled images?
Added code:
var margin = {top: 20, right: 20, bottom: 20, left: 40},
w = 100 - margin.left - margin.right,
h = 100 - margin.top - margin.bottom;
var canvas = d3.select("canvas")
.node();
var context = canvas.getContext('2d');
var scale = d3.scale.linear()
. range([0,w])
.domain([0,h]);
data = d3.range(60000).map(function(){return Math.random()*500});
data.forEach(function(d,i) {
context.strokeStyle="red";
context.lineWidth="1";
context.lineTo(scale(++k),scale(d));
context.stroke();
});
Since you are asking a completely different question in the comment section I thought of put it another answer.
Comments and working code inline.
var margin = {top: 20, right: 20, bottom: 20, left: 40},
w = 100 - margin.left - margin.right,
h = 100 - margin.top - margin.bottom;
var canvas = d3.select("canvas")
.node();
var context = canvas.getContext('2d');
var data = d3.range(11).map(function(){return Math.random()*10})
var x = d3.scale.linear().domain([0, 10]).range([0, 700]);
var y = d3.scale.linear().domain([0, 10]).range([10, 290]);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d,i) {console.log(x(i));return x(i);})
.y(function(d) {return y(d);})
//making a dummy SVG
var path = d3.select("body").append("svg").append("path")
.attr("d", line(data))
.attr("stroke", "steelblue")
.attr("stroke-width", "2")
.attr("fill", "none").remove();
d3.select("body svg").remove();
//going from 0 to the paths total length and storing all the points
var points = [];
for(var i =0; i < path.node().getTotalLength(); i++){
points.push(path.node().getPointAtLength(i));//store point # that length
}
var id = window.setInterval(function(){
console.log("Doing")
var point = points.shift();//take each point
context.strokeStyle="red";
context.lineWidth="1";
context.lineTo(point.x,point.y);
context.stroke();
if(points.length <= 0){
console.log("Finished")
window.clearInterval(id);//clear the interval since the drawing is complete
}
}, 10)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.10/d3.js"></script>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
</canvas>
<script src="script.js"></script>
</body>
</html>
Working code on Plunker.
The problem is here:
data.forEach(function(d,i) {
context.strokeStyle="red";
context.lineWidth="1";
context.lineTo(scale(++k),scale(d));
context.stroke();//this should be out of the for loop you should be doing it once not everytime
});
Something like this:
data.forEach(function(d,i) {
context.strokeStyle="red";
context.lineWidth="1";
var j = scale(d);
var m = scale(d++);
context.lineTo(j,m);
});
context.stroke();
Working code here
Hope this helps!
I'm trying to extend the simple example given in Mike Bostock's Let's Make a Map to allow coloring countries in a map based on whether their name appears in a list.
How do I color Scotland and Wales green and the other countries blue if I've defined a list var selected_countries = ["SCT", "WLS"]?
The following code works for coloring just one country (Scotland) using a conditional if/else statement, but how do I extend this to change the class of all those countries listed in the variable selected_countries? I've tried if(selected_countries.contains(d.id))... but this doesn't work, I'm guessing the scoping is what's tripping me up.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.subunit.selected { fill: green; }
.subunit.not-selected { fill: grey; }
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
var width = 960,
height = 1160;
var projection = d3.geo.albers()
.center([0, 55.4])
.rotate([4.4, 0])
.parallels([50, 60])
.scale(1200 * 5)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var selected_countries = ["SCT", "WLS"]
d3.json("uk.json", function(error, uk) {
svg.selectAll(".subunit")
.data(topojson.feature(uk, uk.objects.subunits).features)
.enter().append("path")
.attr("class", function(d) {
if (d.id == "SCT") {return "subunit selected"}
else {return "subunit not-selected"};
})
.attr("d", path);
});
</script>
There are two (at least) ways to do this:
Have a variable named "blue" or whatever color you want other countries to have. Then use a for loop that goes through all the elements in the list. At each iteration of for loop, make a comparative statement to check if your d.id == <current element in list> or not. Something like:
var color = 'blue'; // or subunit not-selected
for (var i=0; i<lengthOf(selected_countries); i++)
{
if (d.id == selected_countries[i])
color = 'green'; // or subunit selected
}
return color;
You can use the indexOf() method that returns '-1' when the parameter passed is not in the list.
((selected_countries.indexOf(d.id) == -1) ? return blue : return green);
I am trying to display a map on my webpage using D3. The geo data is present in a geojson file. I am using the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<!--<LINK rel="stylesheet" href="style.css" type="text/css">-->
<script type="text/javascript" src="../jslibs/d3_source/d3.v3.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
</script>
</head>
<body>
<script type="text/javascript">
d3.select("body")
.append("p")
.text("D3 is working");
//Variables
var map_width = 960;
var map_height = 1160;
//Append svg
var svg = d3.select("body").append("svg") /*D3 is async. Do this in head to avoid page reorganisation when map arrives*/
.attr("width", map_width)
.attr("height", map_height);
var projection = d3.geo.mercator()
.scale((map_width + 1) / 2 / Math.PI)
.translate([map_width / 2, map_height / 2])
.precision(.1); //Define projection
var path = d3.geo.path().projection(projection); //Define path generator
var g = svg.append("g");
d3.json("./data/MyGeoJSON.geojson", function(error, ug) {
if (error) return console.error(error);
console.log(ug);
g.selectAll("path")
.data(ug.features)
.enter()
.append("path")
.attr("d", path);
});
</script>
</body>
</html>
I am just getting a blank SVG element on my page. No map is getting rendered. I have checked the validity of my GeoJSON file on http://geojsonlint.com/ and http://geojson.io/. Also, I can see the geojson object on the developer console.
I have looked at a few tutorials online and also on StackOverflow and I am not sure where I am going wrong.