|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
text { |
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; |
|
font-size: 18px; |
|
font-weight: bold; |
|
text-anchor: middle; |
|
} |
|
|
|
</style> |
|
<body> |
|
<script src="//code.jquery.com/jquery-2.1.0.min.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.1.0/topojson.min.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3-geo-projection/0.2.9/d3.geo.projection.min.js"></script> |
|
|
|
<script src="../js/wikiatlas.js"></script> |
|
|
|
<script> |
|
/** |
|
* Created with Wikiatlas. |
|
* User: hugolpz |
|
* Version: 2014.09.04 */ |
|
/* ****************************************************** */ |
|
/* MATH TOOLKIT ***************************************** */ |
|
function parallel(φ, λ0, λ1) { |
|
if (λ0 > λ1) λ1 += 360; |
|
var dλ = λ1 - λ0, |
|
step = dλ / Math.ceil(dλ); |
|
return d3.range(λ0, λ1 + 0.5 * step, step).map(function(λ) { return [normalise(λ), φ]; }); |
|
} |
|
function normalise(x) { |
|
return (x + 180) % 360 - 180; |
|
} |
|
/* ****************************************************** */ |
|
/* LOCALISATOR FN *************************************** */ |
|
var localisator = function (hookId,localisator_width, title, WNES0, WNES1, WNES2, WNES3) { |
|
/* Init ************************************************* */ |
|
var width = 1*localisator_width, |
|
height = 1*localisator_width; |
|
var lon_central = function(){ |
|
var num; |
|
if(WNES2<WNES0){ num= -(WNES0+WNES2)/2+180; } |
|
else{ num= -(WNES0+WNES2)/2; } |
|
return num; |
|
}; |
|
|
|
var proj = d3.geo.orthographic() |
|
.scale(1/2*localisator_width) |
|
.rotate([ lon_central(), -(WNES1+WNES3)/2 +10 ]); // orthographic + 10⁰ to simulate real life globe watching. |
|
|
|
var projection2 = proj |
|
.translate([width / 2 , height / 2 ]) |
|
.clipAngle(90); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection2); |
|
|
|
/* SVG container **************************************** */ |
|
var svg = d3.select(hookId).append("svg") |
|
.attr("id", title+"-orthographic_globe_locator_(wikiatlas_2014)") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.call(d3.behavior.drag() |
|
.origin(function() { |
|
var rotate = projection2.rotate(); |
|
return {x: 2 * rotate[0], y: -2 * rotate[1]}; |
|
}) |
|
.on("drag", function() { |
|
projection2.rotate([d3.event.x / 2, -d3.event.y / 2, projection2.rotate()[2]]); |
|
svg.selectAll("path").attr("d", path); |
|
})) |
|
.on("dblclick", function() { |
|
projection2.rotate([ lon_central(), -(WNES1+WNES3)/2 +10 ]); |
|
svg.selectAll("path").attr("d", path); |
|
}); |
|
|
|
/* SVG background *************************************** */ |
|
// Blue circle |
|
svg.append("circle") |
|
.attr("class", "water") |
|
.attr("cx", width/2) |
|
.attr("cy", height/2) |
|
.attr("r", width/2 ) |
|
.style({'fill':'#C6ECFF'}) |
|
.style({'stroke': '656565', 'stroke-width': 1.5}); |
|
// Gradiant settings |
|
var gradient = svg.append("svg:defs") |
|
.append("svg:linearGradient") |
|
.attr("id", "gradient") |
|
.attr("x1", "0%") |
|
.attr("y1", "0%") |
|
.attr("fx1", "30%") |
|
.attr("fy1", "30%") |
|
.attr("x2", "100%") |
|
.attr("y2", "100%") |
|
.attr("spreadMethod", "pad"); |
|
gradient.append("svg:stop") // middle step setting |
|
.attr("offset", "50%") |
|
.attr("stop-color", "#FFF") |
|
.attr("stop-opacity", 0.3); |
|
gradient.append("svg:stop") // final step setting |
|
.attr("offset", "100%") |
|
.attr("stop-color", "#009") |
|
.attr("stop-opacity", 0.3); |
|
// Gradiant-circle |
|
var circle = svg.append('circle') // append gradient to circle |
|
.attr('cx', width / 2) |
|
.attr('cy', height / 2) |
|
.attr('r', width/2 ) |
|
.attr('fill', 'url(#gradient)'); |
|
|
|
/* ****************************************************** */ |
|
/* GIS data injection *********************************** */ |
|
d3.json("world-110m-ids.json", function(error, world) { |
|
/**/ var countries = topojson.feature(world, world.objects.countries).features, |
|
/**/ i = -1, |
|
/**/ n = countries.length; |
|
|
|
var country = svg.selectAll(".country") |
|
.data(topojson.feature(world, world.objects.countries).features) |
|
.enter().append("path") |
|
.attr("id", function(d){ return d.id } ) |
|
.attr("class", "country") |
|
.style("fill", "#FDFBEA") |
|
.attr("d", path); |
|
|
|
var focus = d3.selectAll("#"+title) |
|
.style("fill", "#B10000"); |
|
|
|
var boundaries = svg.append("path") |
|
//.datum( topojson.mesh(world, world.objects.countries, function(a,b) { if (a!==b){var ret = b;}return ret;})) |
|
.datum( topojson.mesh(world, world.objects.countries, function(a,b) { return a!==b; })) |
|
.attr("class", "boundary") |
|
.attr("d", path) |
|
.style({'fill':'none','stroke': '#656565', 'stroke-width': 0.5}); |
|
|
|
var graticule = svg.append("path") |
|
.datum(d3.geo.graticule().step([20,20])) |
|
.attr("class", "graticule") |
|
.attr("d", path) |
|
.style({'fill':'none', 'stroke':'#777', 'stroke-width': 0.5, 'stroke-opacity': 0.5}); |
|
|
|
var coast = svg.append("path") |
|
//.datum( topojson.mesh(world, world.objects.countries, function(a,b) { if (a==b){var ret = b;}return ret;})) |
|
.datum( topojson.mesh(world, world.objects.countries, function(a,b) { return a==b; })) |
|
.attr("class", "Coast_border") |
|
.style({'fill': 'none', 'stroke': '#0978AB', 'stroke-linejoin': 'round'}) |
|
.style({'stroke-width': 0.5 }) |
|
.attr("d", path); |
|
|
|
/* Red graniticule drawing |
|
svg.append("path") |
|
.attr("d", path(d3.geo.graticule() |
|
.majorExtent([[WNES0, WNES3], [WNES2, WNES1]]).outline())) |
|
.style({'fill': '#B10000', 'fill-opacity': 0.3, 'stroke': '#B10000', 'stroke-linejoin': 'round'}) |
|
.style({'stroke-width': 1 }); /**/ |
|
|
|
//* Red polygon drawing |
|
var redwindow = svg.append("path") |
|
.datum({type: "Polygon", coordinates: [ //LineString |
|
[[WNES0,WNES3]] |
|
.concat(parallel(WNES1, WNES0, WNES2)) |
|
.concat(parallel(WNES3, WNES0, WNES2).reverse()) |
|
]}) |
|
.style({'fill': '#B10000', 'fill-opacity': 0.3, 'stroke': '#B10000', 'stroke-linejoin': 'round'}) |
|
.style({'stroke-width': 1 }) |
|
.attr("d", path); /**/ |
|
|
|
var label = svg.append("text") |
|
.attr("x", width / 2) |
|
.attr("text-anchor","middle") |
|
.text(title) |
|
.attr("y", height * 57/100 ); |
|
|
|
|
|
|
|
var step = function() { |
|
if (++i >= n) { i = 0} ; |
|
label.text(countries[i].id); |
|
svg.transition(); |
|
country.transition() |
|
.style("fill", function(d, j) { return j === i ? "#B10000" : "#FDFBEA"; }); |
|
|
|
var centroid = d3.geo.path() |
|
.projection(function(d) { return d; }) |
|
.centroid; |
|
var area = d3.geo.path() |
|
.projection(function(d) { return d; }) |
|
.area; |
|
var bounds = d3.geo.path() |
|
.projection(function(d) { return d; }) |
|
.bounds; |
|
|
|
|
|
d3.transition() |
|
.delay(250) |
|
.duration(1250) |
|
.tween("rotate", function() { |
|
var point = centroid(countries[i]); |
|
var surface = area(countries[i]); |
|
var bb = bounds(countries[i]); |
|
console.log("area: "+surface+"; bb: "+ JSON.stringify(bb) ); |
|
return function(t) { |
|
projection2.rotate([-point[0], -point[1]+10]); // area of interest slide 10⁰ up |
|
country.attr("d", path); |
|
boundaries.attr("d", path); |
|
graticule.attr("d", path); |
|
coast.attr("d", path); |
|
// draw polygon (red frame) bigger than bb: |
|
if (surface <15) { // is visible |
|
redwindow.datum({type: "Polygon", coordinates: [ //LineString |
|
[[bb[0][0]-5,bb[0][1]-5]] |
|
.concat(parallel(bb[1][1]+5, bb[0][0]-5, bb[1][0]+5)) |
|
.concat(parallel(bb[0][1]-5, bb[0][0]-5, bb[1][0]+5).reverse()) |
|
]}) |
|
.style({'fill': '#B10000', "opacity": 1, 'fill-opacity': 0.3}) |
|
.style({'stroke-width': 1, 'stroke-opacity': 1, 'stroke': '#B10000', 'stroke-linejoin': 'round' }) |
|
.attr("d", path); /**/ |
|
} else if (surface >15 ) { // isn't visible |
|
redwindow.style({'opacity': 0}) |
|
} |
|
|
|
}; |
|
}) |
|
.transition() // runs transition |
|
.each("end", function(){ console.log(countries[i].id); return step(); } ); |
|
} |
|
step(); |
|
|
|
}); |
|
|
|
}; |
|
|
|
</script> |
|
<script> |
|
var WNES = { "item":"India", "W": 67.0, "N":37.5, "E": 99.0, "S": 5.0 }; |
|
localisator("body",500, WNES.item, WNES.W, WNES.N, WNES.E, WNES.S); |
|
</script> |