I would like to minimize greenland and antartica on my D3 geojson map. How do I do this. I've tried scale and translate methods but they simply move the map around on the page not providing the minimized y coordinates.
image of map
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="d3.v3.js"></script>
<script src="topojson.min.js"></script>
<style>
</style>
<script type="text/javascript">
function draw(geo_data) {
"use strict";
var margin = 75,
width = 1920 - margin,
height = 1080 - margin;
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin)
.attr("height", height + margin)
.append('g')
.attr('class', 'map');
var projection = d3.geo.mercator();
var path = d3.geo.path().projection(projection);
var map = svg.selectAll('path')
.data(geo_data.features)
.enter()
.append('path')
.attr('d', path)
.style('fill', 'rgb(9, 157, 217)')
.style('stroke', 'black')
.style('stroke-width', 0.5);
};
</script>
</head>
<body>
<script type="text/javascript">
/*
Use D3 to load the GeoJSON file
*/
//d3.json("world-topo-min.json", draw);
d3.json("world_countries.json", draw);
</script>
</body>
</html>
If you want to remove the areas for Greenland and Antarctica on the fly, you can simply filter your GeoJSON FeatureCollection, i.e. geo_data.features. In this array you will find features for both Greenland ("id": "GRL") as well as Antarctica ("id": "ATA"). Hence, you can make use of the array's .filter() method to get rid of these two features leaving the rest untouched:
var map = svg.selectAll('path')
.data(geo_data.features.filter(d => d.id !== "GRL" && d.id !== "ATA))
Related
I am going through D3 Tips & Tricks and i'm on this graph: http://bl.ocks.org/d3noob/7030f35b72de721622b8.
I am playing around with the different axises to get them to re-render and re-size dynamically upon a JavaScript function has been called via a button. I want to re-render the x axis so that it takes longer to fully load than the re-generated line element.
// Select the section we want to apply our changes to
var svg = d3.select("body").transition().delay(500).style("stroke", "green");
// Make the changes
svg.select(".line") // change the line
.duration(750)
.style("stroke", "red")
.attr("d", valueline(data));
svg.select(".x.axis") // change the x axis
.duration(1750)
.call(xAxis);
svg.select(".y.axis") // change the y axis
.duration(1000000000)
.call(yAxis);
});
In theory, I suppose that .duration() command can take the highest integer value that JavaScript accepts as a .millisecond. Is that correct? I am keen to know if there is a limit here as to the longest possible duration I can make.
I just coded up a quick example with Number.MAX_VALUE and d3 doesn't complain:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var svg = d3.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 500);
var c = svg.append('circle')
.attr('transform', 'translate(20,20)')
.attr('r', 20)
.style('fill', 'steelblue');
c.transition()
.duration(Number.MAX_VALUE)
.ease(d3.easeLinear)
.tween("attr.transform", function() {
var self = d3.select(this),
i = d3.interpolateTransformSvg('translate(20,20)', 'translate(400,400)');
return function(t) {
console.log(i(t));
self.attr('transform',i(t));
};
});
</script>
</body>
</html>
Some quick calculations tell me though that it'll take 1x10306 iterations of the transition loop to move my circle 1px, so assuming the transition loop is firing every 17 milliseconds, that's around 5.34 × 10296 years before I see any movement....
I have rendered the world map using world-110m topojson. I directly used the code provided by Jakob on D3 mapping tutorial - http://www.digital-geography.com/d3-js-mapping-tutorial-1-set-initial-webmap/#.V4iGN9J97IV
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Set a style for our worldshape-data -->
<style>
path {
stroke: red;
stroke-width: 0.5px;
fill: grey;
}
</style>
<body>
<!-- implementation of the hosted D3- and TopoJson js-libraries -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v0.min.js"></script>
<!-- map creation -->
<script>
// canvas resolution
var width = 1000,
height = 600;
// projection-settings for mercator
var projection = d3.geo.mercator()
// where to center the map in degrees
.center([0, 50 ])
// zoomlevel
.scale(100)
// map-rotation
.rotate([0,0]);
// defines "svg" as data type and "make canvas" command
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// defines "path" as return of geographic features
var path = d3.geo.path()
.projection(projection);
// group the svg layers
var g = svg.append("g");
// load data and display the map on the canvas with country geometries
d3.json("world-110m.json", function(error, topology) {
g.selectAll("path")
.data(topojson.object(topology, topology.objects.countries)
.geometries)
.enter()
.append("path")
.attr("d", path)
});
// zoom and pan functionality
/*var zoom = d3.behavior.zoom()
.on("zoom",function() {
g.attr("transform","translate("+
d3.event.translate.join(",")+")scale("+d3.event.scale+")");
g.selectAll("path")
.attr("d", path.projection(projection));
});
svg.call(zoom)*/
</script>
</body>
</html>
Now i want to reuse this code to render the map of India. But when I link it to India topoJSON file, only a blank SVG is created. The js console gives an error - topojson.v0.min.js:1 Uncaught TypeError: Cannot read property 'type' of undefined
I have placed world-110m.json and india.json on dropbox -
https://www.dropbox.com/sh/wrxyngyq4jdie9c/AACG2-dTzC79rRvlxlOC5poBa?dl=0
Its just a small error.
topojson.object(topology, topology.objects.countries //wrong
topojson.object(topology, topology.objects.collection // right
Next time check the data, by printing it to console and check its contents.
I have used the code from github (https://github.com/alignedleft/d3-book/blob/master/chapter_12/04_fill.html).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Setting path fills</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.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;
//Define map projection
var projection = d3.geo.albersUsa()
.translate([w/2, h/2])
.scale([500]);
//Define path generator
var path = d3.geo.path()
.projection(projection);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Load in GeoJSON data
d3.json("us-states.json", function(json) {
//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("fill", "steelblue");
});
</script>
</body>
</html>
JSON file is from ( https://github.com/alignedleft/d3-book/edit/master/chapter_12/us-states.json).
Sample:
{"type":"FeatureCollection","features":[
{"type":"Feature","id":"01","properties":{"name":"Alabama"},"geometry":{"type":"Polygon","coordinates":[[[-87.359296,35.00118],[-85.606675,34.984749],[-85.431413,34.124869],[-85.184951,32.859696],[-85.069935,32.580372],[-84.960397,32.421541],[-85.004212,32.322956],[-84.889196,32.262709],[-85.058981,32.13674],[-85.053504,32.01077],[-85.141136,31.840985],[-85.042551,31.539753],[-85.113751,31.27686],[-85.004212,31.003013],[-85.497137,30.997536],[-87.600282,30.997536],[-87.633143,30.86609],[-87.408589,30.674397],[-87.446927,30.510088],[-87.37025,30.427934],[-87.518128,30.280057],[-87.655051,30.247195],[-87.90699,30.411504],[-87.934375,30.657966],[-88.011052,30.685351],[-88.10416,30.499135],[-88.137022,30.318396],[-88.394438,30.367688],[-88.471115,31.895754],[-88.241084,33.796253],[-88.098683,34.891641],[-88.202745,34.995703],[-87.359296,35.00118]]]}},...
But i'm getting an empty HTML page as output. What am i missing?
No i don't see any issues with the code except may be us-states.json be not available in the root folder, where your code is looking for.
You can also access the us-states.json directly from github like this:
d3.json("https://raw.githubusercontent.com/alignedleft/d3-book/master/chapter_12/us-states.json", function(json) {
//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("fill", "steelblue");
});
Working code here
I am a D3 newer and wrote a program to draw a pie ring.
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>pie ring</title>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
var dataset=[{name:A,value:5},{name:C,value:10},{name:F,value:13}];
var pie=d3.layout.pie(dataset);
var h=600;
var w=600;
var outerRadius=w/2;
var innerRadius=w/3;
var arc=d3.svg.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius);
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var color=d3.scale.category10();
var arcs=svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class","arc")
.attr("transform","translate("+outerRadius+","+outerRadius+")");//translate(a,b)
arcs.append("path")
.attr("fill",function(d,i){
return color(i);
})
.attr("d",arc);
arcs.append("text")
.attr("transform",function(d){
return "translate("+arc.centroid(d)+")";
})
.attr("text-anchor","middle")
.text(function(d){
return d.name + ":" + d.value;
});
</script>
</body>
</html>
But failed, I don't know that how to define data structure and don't know how to pie dataset. pie(dataset) or pie(function(d){return d.value} ); could you help me to correct it
the javascript console told me that A is not defined. This A is the value of the name of the dataset. I don't know if the only request is digital value or digital array for pie ring.
Few problems here. It's telling you A isn't defined because it's not. You're using plain text instead of a string, so it thinks A is a variable, not a label. Even if you resolved that, there would be some other issues with the structure.
Copied almost straight from the d3 pie chart example here, I put in your data and it works a charm.
Here's the code, but I also strongly recommend going over the tutorial so you can see how it's supposed to work.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>pie ring</title>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript">
var w = 600;
var h = 600;
var outerRadius=w/2;
var innerRadius=w/3;
color = d3.scale.category20c();
data = [{"label":"A", "value":5},
{"label":"C", "value":10},
{"label":"F", "value":13}];
var vis = d3.select("body")
.append("svg:svg")
.data([data])
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
var arc = d3.svg.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius);
var pie = d3.layout.pie()
.value(function(d) { return d.value; });
var arcs = vis.selectAll("g.slice")
.data(pie)
.enter()
.append("svg:g")
.attr("class", "slice");
arcs.append("svg:path")
.attr("fill", function(d, i) { return color(i); } )
.attr("d", arc);
arcs.append("svg:text")
.attr("transform", function(d) {
d.innerRadius = innerRadius;
d.outerRadius = outerRadius;
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d, i) { return data[i].label; });
</script>
</body>
</html>
I'm having an issue with a d3 zoomable map.
I'm loading the map from a previously built topojson file with a departmentsobject (the areas in the map) and a maternidadesobject (a few points in the map, initially rendered with crosses).
I'm using d3.behavior.zoom to implement the zoom behaviour, and I want it to be able to zoom using the mouse wheel and pan with drag. It works just fine with the map itself (the areas). However, the points in the map get shifted instantly to a wrong location at any zoom event. Also, the points' path is changed from crosses to circles somehow!
You can reproduce the issue and view the code here: http://bl.ocks.org/monsieurBelbo/5033491
Here is code:
<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.js"></script>
<script src="topojson.v0.min.js"></script>
<html>
<style>
.background {
fill: none;
pointer-events: all;
}
.department {
fill: #aaa;
stroke: #fff;
stroke-width: 1.5px;
}
</style>
<body>
<script>
d3.json("santafe.json", function(error, theProvince) {
var width= 960, height= 500;
var svg = d3.select("body").append("svg");
var departments = topojson.object(theProvince, theProvince.objects.departments);
// The projection
var projection = d3.geo.mercator()
.scale(14000)
.center([-60.951,-31.2])
.translate([width / 2, height / 2]);
// The path
var path = d3.geo.path()
.projection(projection);
// Zoom behavior
var zoom = d3.behavior.zoom()
.translate(projection.translate())
.scaleExtent([height, Infinity])
.scale(projection.scale())
.on("zoom", function() {
projection.translate(d3.event.translate).scale(d3.event.scale)
map.selectAll("path.zoomable").attr("d", path);
});
// The map
var map = svg.append("g")
.classed("provinceMap", true)
.call(zoom);
map.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
// Departments
map.selectAll(".department")
.data(departments.geometries)
.enter().append("path")
.classed("department", true)
.classed("zoomable", true)
.attr("d", path);
// Places
map.selectAll(".place-label")
.data(topojson.object(theProvince, theProvince.objects.maternidades).geometries)
.enter().append("path")
.classed("place", true)
.classed("zoomable", true)
.attr("d", d3.svg.symbol().type("cross"))
.attr("transform", function(d) { return "translate(" + projection(d.coordinates.reverse()) + ")"; });
});
</script>
</body>
</html>
Any ideas?
Thanks!
UPDATE
Thanks to #enjalot 's suggestion, the issue was solved by re-translating the places on the zoom behaviour. Just add:
map.selectAll(".place").attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; });
to the zoom behavior. Check out a working version here: http://tributary.io/inlet/5095947