Published
Edited
Jun 16, 2021
Fork of EEZ Shapes
Importers
1 star
Insert cell
md`# EEZ Globe`
Insert cell
viewof rotate = DOM.range(0, 360, 1)
Insert cell
width =150
Insert cell
height = width * 1.1
Insert cell
sphere = ({type: "Sphere"})
Insert cell
mutable name = ""
Insert cell
canvas2 = {
const context = DOM.context2d(width, height);
var UKcoords = d3.geoCentroid(EEZshapes.features[0])
// const projection = d3.geoOrthographic().fitExtent([[10, 10], [width - 10, height - 10]], sphere);
var projection = d3.geoOrthographic()
.rotate([-UKcoords[0], -UKcoords[1]])
.scale(400)
.translate([width/2, height/2])
.clipAngle(15)
.precision(10);
// const projection = d3.geoOrthographic().fitExtent([[10, 10], [width - 10, height - 10]], sphere);
const path = d3.geoPath(projection, context);
function render(focalEEZ) {
context.clearRect(0, 0, width, height);
context.beginPath(), path(land), context.fillStyle = "#ccc", context.fill();
for (const EEZ of EEZshapes.features) {
if (EEZ.properties.SOVEREIGN1 === focalEEZ) {
context.beginPath(), path(EEZ),context.fillStyle = "red",context.fill();
}
}
context.beginPath(), path(sphere), context.strokeStyle = "#000", context.lineWidth = 1.5, context.stroke();
return context.canvas;
}
let p;
for (const EEZ of EEZshapes.features) {
let name = EEZ.properties.SOVEREIGN1;
yield render(name);
p = d3.geoCentroid(EEZ);
const ip = d3.interpolate(projection.rotate(), [-p[0], -p[1]])
await d3.transition()
.duration(2000)
.tween("render", () => t => {
projection.rotate(ip(t));
render(name);
})
.end();
}



}
Insert cell
countryNames = ["United Kingdom","Ireland","France","Denmark","Sweden","Germany","Spain","Netherlands","Finland"]
Insert cell
highlightEEZ("United Kingdom")
Insert cell
showMap(mapColor)
Insert cell
viewof mapColor = DOM.input('color')
Insert cell
muteGlobe2()
Insert cell
muteGlobe()
Insert cell
muteGlobe = function(){

d3.selectAll("#landBackground")
.attr("opacity",0.4);

d3.select("#focal-EEZ-text")
.text("Hover over an EEZ bar")
.attr("opacity",1);
d3.select(".map").selectAll(".EEZs")
.remove();

}
Insert cell
muteGlobe2 = function(){

d3.selectAll("#landBackground")
.transition().duration(2000)
.attr("opacity",0.4);

d3.select("#focal-EEZ-text")
.attr("opacity",0)
.text("Hover over an EEZ bar")
.transition().duration(2000)
.attr("opacity",1);
d3.select(".map").selectAll(".EEZs")
.remove();
}
Insert cell
showMap = function(color) {
var map = d3.select(DOM.svg(width, height))
.attr("class", "map")
.style("background-color","#ebecee")
let defs = map.append("defs");
defs.append('filter')
.attr('id','blur')
.append('feGaussianBlur')
.attr('stdDeviation',3);
defs.append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path)
.style("fill", "#F5F5F5")
.style("stroke","#78909c") ;
map.append("text")
.attr("dy",-5)
.append("textPath") //append a textPath to the text element
.attr("xlink:href", "#sphere") //place the ID of the path here
.style("text-anchor","middle") //place the text halfway on the arc
.attr("startOffset", "29%")
.attr("id", "focal-EEZ-text")
.text("United Kingdom")
.style("font-family","Lato")
.style("font-size",14)
.style("fill","#78909c");

map.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
// map.append("use")
// .attr("class", "stroke")
// .attr("xlink:href", "#sphere")
map.append("use")
.attr("xlink:href", "#sphere")
.style("filter","url(#blur)")
//background land
for (let i = 0; i < countries.length; i++) {
map.append("path").attr("id","landBackground")
.datum(countries[i])
.attr("fill", "darkgrey")
.attr("d", path)
.attr("data-country-id", i)
.style("fill", color);
// .style("fill", mapColor);

}
// map.append("use")
// .attr("id", "sphereOverlay")
// .attr("class", "fill")
// .attr("opacity",0)
// .attr("xlink:href", "#sphere");

return map.node()


}
Insert cell
highlightEEZ = function(focalEEZ, callback){
let focalShapes = EEZshapesSorted.filter(d => d.properties.SOVEREIGN1 == focalEEZ)
let map = d3.select(".map")
d3.selectAll("#landBackground")
.attr("opacity",1);
d3.select("#focal-EEZ-text")
.text(focalEEZ)
.style("fill","#78909c");
let bind = map.selectAll(".EEZs")
.data(focalShapes, d => d.index)
bind.enter().append("path")
.datum(d => d)
.attr("d", path)
.attr("class", "EEZs")
.attr("data-country-id", `${focalEEZ}`)
.style("fill", d => colorScale(d.index))
bind.exit().remove()
d3.transition()
.duration(1250)
.tween("rotate", function(){
var p = d3.geoCentroid(...focalShapes),
r = d3.interpolate(projection.rotate(), [-p[0], -p[1]]);
return function(t) {
projection.rotate(r(t));
map.selectAll("path").attr("d",path)
}
}).on("end", callback)
// return map.node()
}
Insert cell
projection = {
var UKcoords = d3.geoCentroid(EEZshapesSorted[0])

var projection = d3.geoOrthographic()
.rotate([-UKcoords[0], -UKcoords[1]])
.scale(270)
.translate([width/2, height/2])
.clipAngle(13)
.precision(10);
return projection

}
Insert cell
path = d3.geoPath()
.projection(projection);
Insert cell
EEZshapesSorted = {
let EEZshapesSorted = []
countryNames.map(function(d,i){
let data = EEZshapes.features.filter(v => v.properties.SOVEREIGN1 === d);
data[0].index = i
EEZshapesSorted.push(...data);
})
return EEZshapesSorted

}
Insert cell
colorScale = d3.scaleLinear()
.domain(d3.extent(d3.range(countryNames.length)))
.range(["#B53471", "#12CBC4"])
.interpolate(d3.interpolateHcl)
Insert cell
viewof rotation = DOM.range(0,360,1)
Insert cell
EEZshapes = FileAttachment("EU_EEZ_Min_Sov.geojson").json()
Insert cell
countries = topojson.feature(world, world.objects.countries).features
Insert cell
land = topojson.feature(world, world.objects.land)
Insert cell
world = d3.json("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json")
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3@6")
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more