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>
Related
I am trying to create a simple plot that is zoomable, pannable, and dynamically resizes with the window. In this case I only want it be to zoomable and pannable on the x axis. I'm using d3 v4.
The main issue I have run into is that the domain of the bottom axis will shift/slide when the page is being resized after the plot has been transformed. On resizing without having first transformed the plot, the bottom axis behaves as desired and maintains its domain, just "compressing" and "expanding" on resize.
To see the desired behavior, you can resize the plot without first transforming the plot by zooming or panning, and you'll see that the bottom axis maintains its domain.
To see the undesirable behavior, you can pan or zoom the plot and then resize the page. You will notice that the domain of the bottom axis will slide/shift.
I suspect there is something I'm doing wrong with setting my scales, however I am quite stuck.
The snippet below is a minimum working example of what I am working with:
window.addEventListener("resize", redraw);
let parentRect = $("#i3061007142472").parent()[0].getBoundingClientRect();
let pWidth = parentRect.width;
let pHeight = parentRect.height;
var margin = {
'top': 10,
'right': 30,
'bottom': 30,
'left': 60
},
width = pWidth - margin.left - margin.right,
height = pHeight - margin.top - margin.bottom;
var svg = d3.select("#i3061007142472")
.attr("width", width)
.attr("height", height + 20);
var zoom = d3.zoom();
zoom.on("zoom", zoom_handler_dataplot);
d3.select("#i3061007142472").call(zoom);
var x_i3061007142472 = d3.scaleTime()
.domain([new Date('0'), new Date('10')])
.range([60, width]);
x_i3061007142472.type = "time";
var svg_gX = svg.append("g")
.attr("class", "xAxis dataplot")
.attr("transform", `translate(0, ${height})`)
svg_gX.call(d3.axisBottom(x_i3061007142472).ticks(5));
var y_i3061007142472 = d3.scaleLinear()
.domain([0, 10])
.range([height, 0]);
y_i3061007142472.type = "linear";
let vd_xaxis_i3061007142472 = x_i3061007142472.copy();
let vd_yaxis_i3061007142472 = y_i3061007142472.copy();
var svg_gY = svg.append("g")
.attr("class", "yAxis dataplot")
.style("padding-left", "50px")
.attr("transform", "translate(" + 60 + ", 0)")
.call(d3.axisLeft(y_i3061007142472).ticks(5));
allow_pan_dir = "x";
domain = x_i3061007142472.domain();
function zoom_handler_dataplot() {
if (allow_pan_dir != "none") {
if (allow_pan_dir == "x" || allow_pan_dir == "both") {
vd_xaxis_i3061007142472 = d3.event.transform.rescaleX(x_i3061007142472);
domain = vd_xaxis_i3061007142472.domain()
svg_gX.call(d3.axisBottom(vd_xaxis_i3061007142472));
} else {
vd_xaxis_i3061007142472 = x_i3061007142472;
}
if (allow_pan_dir == "y" || allow_pan_dir == "both") {
vd_yaxis_i3061007142472 = d3.event.transform.rescaleY(y_i3061007142472);
svg_gY.call(d3.axisLeft(vd_yaxis_i3061007142472));
} else {
vd_yaxis_i3061007142472 = y_i3061007142472;
}
}
}
function redraw() {
console.warn("calling redraw");
console.warn(allow_pan_dir);
chartWidth = parseInt(d3.select(".dataplot_i3061007142472").style("width"));
chartHeight = parseInt(d3.select(".dataplot_i3061007142472").style("height"));
height = chartHeight - margin.top - margin.bottom + 20;
x_i3061007142472.range([60, chartWidth]);
y_i3061007142472.range([chartHeight - 30 - 10 + 20, 0]);
if (allow_pan_dir == "x" || allow_pan_dir == "both") {
vd_xaxis_i3061007142472 = d3.zoomTransform(d3.select("#i3061007142472").node()).rescaleX(x_i3061007142472);
svg_gX.call(d3.axisBottom(vd_xaxis_i3061007142472));
} else {
vd_xaxis_i3061007142472 = x_i3061007142472;
}
if (allow_pan_dir == "y" || allow_pan_dir == "both") {
vd_yaxis_i3061007142472 = d3.zoomTransform(d3.select("#i3061007142472").node()).rescaleY(y_i3061007142472);
svg_gY.call(d3.axisLeft(vd_yaxis_i3061007142472));
} else {
vd_yaxis_i3061007142472 = y_i3061007142472;
}
let currTransform = d3.zoomTransform(d3.select('#i3061007142472').node());
d3.select("#i3061007142472").call(zoom.transform, currTransform);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./styles.css ">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.0.0/d3.min.js" integrity="sha512-il/oXcqETt5LGGmWWbOZLxrDgQQXlr7+ZI37ksA//3e9mxFloAOzlkF8SqtMOlWL6zTCk8hPYUQnreiQvT4elQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU=" crossorigin="anonymous"></script>
</head>
<body>
<div id="my_plot" style="display: flex; flex: 1;">
<svg id="i3061007142472" class="dataplot_i3061007142472 dataplot"></svg>
</div>
<script src="./app.js"></script>
</body>
</html>
I tried changing the domain on resize to match the transformed, tried using an intermediary scale, tried modifying the reference scale.
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 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);
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 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.