Yesterday I asked what would be the best method of creating an overlay in a web map that would allow for some interactivity.
Create interactive map with no server
Thanks to a variety of people who recommended I go down the D3 and Topojson route.
The example that looks like the perfect solution is http://bl.ocks.org/mbertrand/5218300
So I created a topojson from an ESRI Shapefile using the following command
topojson --id-property full_name -o southeast.json southeast.shp
I have since tried every possible permutation and example to try and get the topojson loaded and I have hit a brick wall. I just do not understand what I am doing wrong.
I have used the following examples
http://www.schneidy.com/Tutorials/MapsTutorial.html
https://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object
Conversion from Shapefile to TopoJSON format results in incorrect map when rendered using d3js
http://milkator.wordpress.com/2013/02/25/making-a-map-of-germany-with-topojson/
and Mike's original example
http://bost.ocks.org/mike/map/
Maybe it is because i am not using EPSG:4326, but this example says that you do not have to use a projection
http://bl.ocks.org/mbostock/5557726
The data can be found here – https://www.dropbox.com/s/dfxxi4xwrsdfa8t/southeast.json
And this is my code
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
var width = 500,
height = 500;
//null projection as my ESPG is not supported
var path = d3.geo.path()
.projection(null);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("rect").attr('width', width).attr('height', height)
.style('stroke', 'black').style('fill', 'none');
//d3.json("southeast.json", function(error, south) {
//console.log(south);
//});
d3.json("southeast.json", function(error, uk) {
svg.append("path")
.datum(topojson.feature(uk, uk.objects.southeast))
.attr("d", d3.geo.path().projection(null));
});
I first tested with sending the data to the console and that worked fine and told me that the object is "southeast".
If I try this I get an n is not defined error in Firebug.
I then tried
// d3.json("southeast.json", function(error, south) {
// svg.append("path")
// .datum(topojson.feature(south, south.objects.southeast))
// .attr("d", d3.geo.path().projection(null))
// .style("fill", "red")
// .style("stroke-width", "1")
// .style("stroke", "black");
// });
Which seems to work as there are no Firebug errors, but no data is visible
Then I tried
// d3.json("southeast.json", function(error, uk) {
// svg.selectAll(".southeast")
// .data(topojson.feature(uk, uk.objects.southeast).features)
// .enter().append("path")
// .attr("d", path)
// });
And the same thing happens
With no errors I am struggling to understand what I have done wrong
If I could just make this example work in EPSG:27700 with my topojson it would be amazing
http://bl.ocks.org/mbertrand/5218300
Thanks
EDIT
One of the other answers was to use a simply getJSON function and add the data as geojson in OpenLayers. I have just tested it using the same topojson:
$.getJSON('southeast.json', function (data) {
fusiegem = topojson.feature(data, data.objects.southeast);
var geojson_format = new OpenLayers.Format.GeoJSON();
var vector_layer = new OpenLayers.Layer.Vector();
osMap.addLayer(vector_layer);
vector_layer.addFeatures(geojson_format.read(fusiegem));
});
And that successfully loaded, so it seems there is nothing wrong with my topojson file, it is the D3 bit that does not seem to work correctly
Best Answer
If I understand correctly (the file is not available anymore so I could not check), the problem is related to the projection.
In the http://bl.ocks.org/mbostock/5557726 example, a null projection can be used because the topojson file is already in screen coordinates thanks to the options: --width 960 --height 800 during the topjson file generation. In your case, since you didn't specify those options, you will likely need to define a projection (d3.geo.albers for example).