D3 + Leaflet: Canadian 2011 Polling Districts.
Adapted from Mike Bostock's D3 + Leaflet
forked from Brideau's block: D3 + Leaflet for Canada
xxxxxxxxxx
<meta charset="utf-8">
<html>
<head>
<title>XML markers to circle (D3, Leaflet, Turf, Stamen)</title>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.2/leaflet.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.2/leaflet.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/turf.js/3.0.14/turf.min.js"></script>
<script src="//maps.stamen.com/js/tile.stamen.js?v1.3.0"></script>
</head>
<body>
<script type="text/javascript">
d3.xml('markers.xml', function(err, xml) {
if (err) throw err;
// xml sample
var xmlsample = [
'<marker type_facilities="1" id="TPZ64" strName="SKUDAI ENTRY" decLocation="14.80" decLong="103.646355" decLat="1.581686" idhighway="1" type_signature="0" type_facility="0" type_cctv="0" waypoint="0" startSeq="1" endSeq="167" idRoute="7" strPicture="" iconBrand="" />',
'<RSA128_6 description="Petrol Station" strIcon="" intFacilityType="0" iconBrand="PETRONAS.png" strPicture="" />',
];
var hash={};
// find fields from xml sample
var fields = {};
xmlsample.forEach(function(sample) {
var str = sample.replace(/^<\w+\s+/,'').replace(/\s*\/\>$/,'').split(/\" /).forEach(function(k){
k = k.replace(/=\".*$/,'');
fields[k]=1;
});
});
// process loaded xml
var xmldata = [].map.call(xml.querySelectorAll("marker"), function(d) {
var k = {};
for (var t in fields) {
k[t] = d.getAttribute(t);
}
return k;
});
features = xmldata.filter(function(d){ return +d['type_facilities']==1 }).map(function(d){
return turf.point([+d['decLong'],+d['decLat']],d);
});
var bbox = turf.bbox(turf.featureCollection(features));
var midx = bbox[0]+(bbox[2]-bbox[0])/2,
midy = bbox[1]+(bbox[3]-bbox[1])/2;
d3.select('body').append('div').attr('id','map')
.style({
width: '960px',
height: '600px'
});
// leaflet
var map = L.map('map').setView([midy, midx], 7);
// stamen layer
var layer = new L.StamenTileLayer("toner-lite");
map.addLayer(layer);
// https://jsfiddle.net/cvs5d7o9/2/
function projectPointD3(x, y) {
// new L.LatLng creates a new lat/lng object with "lat" and "lng" as
// keys. Topojson uses the (lng,lat) ordering so the x and y need to be
// reversed. Equivalent to [y,x], or {lon:x, lat:y}
var pointLatLng = new L.LatLng(y, x);
// latLngToLayerPoint takes the lat/lng point and returns the x and y
// coordinate for the point on the screen.
var point = map.latLngToLayerPoint(pointLatLng);
this.stream.point(point.x, point.y);
}
// Does plain old projecting from lat/lng to
// an x/y coordinate
function projectPoint(lat, lng) {
var pointLatLng = new L.LatLng(lat, lng);
var point = map.latLngToLayerPoint(pointLatLng);
return point
}
var transform = d3.geo.transform({point: projectPointD3}),
path = d3.geo.path().projection(transform);
//----------------
// add circle
//----------------
var svg = d3.select(map.getPanes().overlayPane).append("svg").style('overflow','visible'),
g = svg.append("g").attr("class", "leaflet-zoom-hide");
var feature = g.selectAll("circle")
.data(features, function(d){ return d.properties.id })
.enter().append("circle")
.attr({
cx: function (d) {
return projectPoint(d.properties['decLat'], d.properties['decLong']).x;
},
cy: function (d) {
return projectPoint(d.properties['decLat'], d.properties['decLong']).y;
},
r:7,
fill:'lime'
})
.on({
mouseover: function(d){
d3.select(this).transition().attr({r:15, fill:'red'});
},
mouseout: function(d){
d3.select(this).transition().attr({r:7, fill:'lime'});
}
});
// viewreset no longer works on leaflet v1.*
map.on("zoom", resetView);
resetView();
function resetView() {
feature.attr({
cx: function (d) {
return projectPoint(d.properties['decLat'], d.properties['decLong']).x;
},
cy: function (d) {
return projectPoint(d.properties['decLat'], d.properties['decLong']).y;
},
});
}
});
</script>
</body>
</html>
Updated missing url //cdnjs.cloudflare.com/ajax/libs/Turf.js/3.0.14/turf.min.js to //cdnjs.cloudflare.com/ajax/libs/turf.js/3.0.14/turf.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js
https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.2/leaflet.js
https://cdnjs.cloudflare.com/ajax/libs/Turf.js/3.0.14/turf.min.js
https://maps.stamen.com/js/tile.stamen.js?v1.3.0