D3 geo node plotting on map? - javascript

I've recently created this D3 map which I had intended to put nodes on the map with links between each node. However I don't know how to do this without using force layout. So far I have created a map of the world using d3 geo map. I have seen a couple of examples of the lines e.g. http://datamaps.github.io/old.html but these don't have nodes on the end of them. I've put my version on JSFiddle which can be found here: http://jsfiddle.net/GarrettUK/n396w4vq/2/.
I'm sure the way to do the lines would be like this:
var election = new Datamap({
scope: 'world',
element: document.getElementById('arcs'),
projection: 'mercator'
});

I would refer you back to the Data Maps arc tutorial.
http://datamaps.github.io/
As far a creating nodes, you could always just append an image to your map using the d3.append and then decide what attributes if any to assign those images. If your looking for the classic node, just append a circle by doing something like this.
var img = g.append("svg:image")
.attr("xlink:href", "circle")

Related

Visualising a custom map with QGIS and D3.js is harmed by the projection

These are 4 polygons I have: http://imgur.com/vsVjxE1 in QGIS. I now wanted to use them with D3.js. I already tried out the things in QGIS generated shapefile malformed when converted to topojson by mapshaper. That was working well on the old json file. But when I was creating a new one, it was bugging in the vertical middle. That's the example http://jsfiddle.net/kwoxer/kpL1uyy2/5/:
var projection = d3.geo.projection(function(x, y) { return [x, y];})
.precision(0).scale(1).translate([0, 0]);
var path = d3.geo.path().projection(projection);
I also tried:
var path = d3.geo.path().projection(null);
but then the whole map was mirrored in the middle.
I think I don't use that system correctly I must assume. The json is fine on mapshaper, too. So do you have some tips, so that I just draw anything I want however big it is and then d3.js is able to draw it as it is. =)
Maybe by
normalizing lan/lng
disabling KBS
I really don't know why creating an own map is not straithforward.
Edit1: found nearly my issue here https://gis.stackexchange.com/questions/54373/either-geojson-to-topojson-conversion-problem-or-projection-issue-with-d3-js but I got:
C:\Program Files\GDAL>ogr2ogr.exe -f "GeoJSON" -s_srs region.prj -t_srs EPSG:432
6 asdas.json region.shp
ERROR 4: Failed to create GeoJSON datasource: asdas.json.
GeoJSON driver failed to create asdas.json
Edit2: already found this interesting answer: https://gis.stackexchange.com/questions/14731/how-do-i-specify-a-crs-for-a-fictional-game-map-in-qgis
But I used such a projection like he used, but still failing with d3.js.
I'm just using an own projection now:
+proj=eqc +a=1790493.11 +lat_ts=0 +lon_0=0 +rf=800 +units=m +no_defs
With that projection all is fine.

How to make multiple charts with d3.chart using nested data

I'm trying to create several charts using the d3.chart framework. This seems like it would be a common use case: the whole point of d3.chart is for the charts to be reusable after all! If you can just point me to an example that would be awesome (:
I went through this (https://github.com/misoproject/d3.chart/wiki/quickstart) tutorial to create a very basic "circle graph". (I copied the code exactly). Now what I want to do is create a separate chart for several sets of data.
I edited it slightly.
Before editing, to set up the chart we called:
var data = [1,3,4,6,10];
var chart = d3.select("body")
.append("svg")
.chart("Circles")
.width(100)
.height(50)
.radius(5);
chart.draw(data);
I tried to change it to:
var data = [{key:1, values:[1,3,4,6,10]},
{key:2, values:[5,2,10,8,11]},
{key:3, values:[1,5,9,16,12]}]
var chart = d3.select("body")
.selectAll("chart)
.data(data)
.enter()
.append("svg")
.chart("Circles")
.width(100)
.height(50)
.radius(5);
chart.draw(function(d) { return d.values; });
This doesn't work however. You can see the corner of a circle in 3 diferent places, but
the rest of it is cut off. However if replace
chart.draw(function(d) { return d.values; });
with
chart.draw([1,3,4,6,10]);
it correctly generates 3 circle graphs, all with that one dataset. And when I add
chart.draw(function(d) { console.log(d.values) return d.values; });
The console shows the 3 arrays I'm trying to pass it! I don't understand what is happening here that's breaking the code. Shouldn't it be the exact same thing as passing the actual arrays to 3 separate charts?
Here's a link to the JS bin with it set up: http://jsbin.com/jenofovogoke/1/edit?html,js,console,output Feel free to mess around with it!
The code is wayyy at the bottom.
I'm pretty new to java script and d3, and entirely new to d3.chart. Any help would be super appreciated!
I asked Irene Ros, who helps run d3.chart, and she informed me that the problem is that d3.chart's draw method can only take an array or a data object- it cannot take a function. She gave me a few helpful hints for ways to get around this: by using a transform function to edit my data within the chart, rather than using a function, or by creating a chart that holds multiple charts (see https://gist.github.com/jugglinmike/6004102 for a great example of this).
However in the end I found the simplest solution for me was to manually set the data. It feels like a bit off a hack because D3 does this for you already, but it was much simpler than changing the whole set up of my chart, and allows for nested data (yay!).
var svg = d3.select("body")
.selectAll("svg")
.data(data)
.enter()
.append("svg");
svg.each(function(d, i) {
var chart = d3.select(this)
.chart("Circles")
.height(50)
.width(100)
.radius(5)
var data = d.values;
chart.draw(data);
});

Using d3 in Leaflet

This is a follow up question to my other one.
http://fiddle.jshell.net/zw8TR/16/
I have managed to utilise d3 to visualise the route between my map markers. I used this example by Mike Bostock as guidance.
The reason I'm using d3 for this instead of Leaflets built in Polyline, is because I'd like to experiment with d3's interpolation to smooth out some routes, and also create arc's for others (for flight routes). At this stage though, I'm just trying to find a way to get these to work for all routes.
The examples I've seen only use the interpolate() method with d3.svg.line(), whereas the Leaflet integration requires me to use d3.geo.path(). Is there a place in my code where it's possible to use this method with d3.geo.path()?
Another possibly helpful link.
And another.
Thanks for any help.
Doing this is a bit messier than using d3.geo.path because that already implements all the boilerplate functionality you need for maps, but it's certainly possible. The idea is to extract the list of user coordinates from the geo path and translate them to screen coordinates in the line function. This translation can be done in the .x() and .y() functions of the line.
var path1 = d3.svg.line()
.interpolate("cardinal")
.x(function(d) { return map.latLngToLayerPoint(new L.LatLng(d[1], d[0])).x; })
.y(function(d) { return map.latLngToLayerPoint(new L.LatLng(d[1], d[0])).y; });
Now we just need to extract the coordinates from the feature.
feature.attr("d", function(d) { return path1(d.geometry.coordinates); });
Complete example here.

Leaflet: add same layer to two different maps

I am displaying two different leaflet maps in the same page. After a certain event. I want a Polyline to appear on both of them. I would like to avoid, if possible, to create a copy and keep two different variables.
I am trying yo use the following:
var line_coordinates = [[1,2],[3,4]];
var my_polyline = L.polyline(line_coordinates);
my_polyline.addTo(map1);
my_polyline.addTo(map2);
However, if I run the above code, the Polyline will be displayed only on the map2.
Afterwords, I will need to change again its coordinates to some new_line_coordinates, and I will run the following:
my_polyline.setLatLngs(new_line_coordinates);
my_polyline.redraw();
The polyline should now appear updated to the new coordinates. However, again, it appears only on map2.
What am I doing wrong? Is it possible to achieve what I am trying to do?
As geocodezip mentioned in a comment, adding a polyline to a map sets the polyline object's this._map instance variable. Therefore, there is no way to have the object rendered on both maps with the way in which it is currently implemented.
You can view the relevant source code here.
You can't add the same layer to multiple Leaflet maps. But I had a similar problem using a more complex GeoJSON layergroup and ultimately solved it by getting the GeoJSON object from the layer using toGeoJSON() and using it to create a new layer for the second map. For a simple polyline, you could use getLatLngs(). So:
var line_coordinates = [[1,2],[3,4]];
var my_polyline = L.polyline(line_coordinates);
my_polyline.addTo(map1);
var new_polyline = L.polyline(line_coordinates);
new_polyline.addTo(map2);
should work, as would:
var line_coordinates = [[1,2],[3,4]];
var my_polyline = L.polyline(line_coordinates);
my_polyline.addTo(map1);
var my_polyline_latlngs = my_polyline.getLatLngs();
var new_polyline = L.polyline(my_polyline_latlngs);
new_polyline.addTo(map2);

SVG to HTML map and area

I have been trying to convert map in SVG to HTML area map for three days. I`am trying to do that with this SVG.
I've tried to convert this SVG with several methods and programs, but all of them failed.
e.g.: inkscape, inkscapeMap, Adobe Illustrator, Polygonator, SVGtoHTML and more.
So I wrote my own PHP script to do the job. Its works fine, but it converts only polygons. But there are two paths in SVG which need to be convert to polygon as well. I've tried to convert these paths into polygons in Illustrator and Inkscape, but apparently there is no way how to force these programs to convert path into polygons. (SVG editors probably decide alone, if they do the conversion or not). I find this topic on SO. But I'am not able to get the JS work - I dont know what the param sample is, and more - browser said that function createElementNS is unknown.
The best result I'am able to reach is this HTML, but there is still two region missing (because they are in SVG in paths)
I would be pleased for any clue.
QUESTIONS
1) How to transform SVG paths into polygons? Is that possible?
2) Is there any software which converts SVG into HTML area maps?
3) Could you show my example parametrs, in this JS function (function written Phrogz):
function polygonSampledFromPath(path,samples){
var doc = path.ownerDocument;
var poly = doc.createElementNS('http://www.w3.org/2000/svg','polygon');
var points = [];
var len = path.getTotalLength();
var step = step=len/samples;
for (var i=0;i<=len;i+=step){
var p = path.getPointAtLength(i);
points.push( p.x+','+p.y );
}
poly.setAttribute('points',points.join(' '));
return poly;
}
3ad) Why is function createElementNS unknown?
PS: I hope you understand my English :)

Categories

Resources