|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Brazilian States: Albers vs Mercator projections</title> |
|
|
|
<script src="https://d3js.org/d3.v5.min.js"></script> |
|
<script src="https://d3js.org/d3-queue.v3.min.js"></script> |
|
<script src="https://d3js.org/topojson.v2.min.js"></script> |
|
|
|
<style> |
|
#br-maps .state { |
|
fill: #bfe; |
|
stroke:black; |
|
fill-opacity: 0.6; |
|
} |
|
#br-maps .state:hover { fill: #d78; } |
|
|
|
/*#br-maps .state_contour { |
|
fill: none; |
|
stroke: black; |
|
stroke-linejoin: round; |
|
|
|
}*/ |
|
|
|
#br-maps rect.map_canvas { |
|
stroke: #F00; |
|
fill: none; |
|
stroke-width: 4; /* 0.25 to 5 */ |
|
opacity: 0.6; /* 0 to 0.5 */ |
|
} |
|
#br-maps .map_gridCell { |
|
stroke: #F55; |
|
fill: none; |
|
stroke-width: 2; /* 0.25 to 5 */ |
|
opacity: 0.9; /* 0 to 0.5 */ |
|
} |
|
</style> |
|
|
|
|
|
<script> |
|
'use strict'; |
|
|
|
// Configs and global vars |
|
const canvas_width=420, // sugere-se 340 a 620 |
|
nX=9, nY=10; |
|
const height=1.1111111111*canvas_width; |
|
const cellWidth = canvas_width/nX; |
|
const cellHeight = height/nY; |
|
|
|
var svg1, svg2, g1, g2, path1, path2; |
|
|
|
function ready(shp) { |
|
var states = topojson.feature(shp, shp.objects.estados); |
|
g1.selectAll(".estado") |
|
.data(states.features) |
|
.enter() |
|
.append("path") // polygon |
|
.attr("class", "state") |
|
.attr("d", path1); |
|
|
|
g2.selectAll(".estado") |
|
.data(states.features) |
|
.enter() |
|
.append("path") // polygon |
|
.attr("class", "state") |
|
.attr("d", path2); |
|
} |
|
|
|
|
|
// // // AlMrCmp |
|
// canvas configs for runAlMrCmp(): |
|
const cv_reduction = 0.7; // reduction factor |
|
const cv_width = 960 *cv_reduction; |
|
const cv_height = 500 *cv_reduction; |
|
const cv_margin = 10 *cv_reduction; |
|
const fontSize = cv_reduction<0.7? "10pt": "12pt"; |
|
|
|
function runAlMrCmp() { |
|
const svgAlMrCmp = d3.select("#AlMrCmp") |
|
.attr("width",cv_width) |
|
.attr("height",cv_height) |
|
; |
|
const mercator = d3.geoMercator(); // Standard Mercator |
|
const albers = d3.geoAlbers() // official Brazilian Statistical Grid |
|
.parallels([-2,-22]) |
|
.rotate([54,0]) |
|
; |
|
var projections = [albers,mercator]; |
|
var projLayout = [ |
|
{label:"ALBERS", color:"crimson", label_x:cv_width/30, label_y:cv_height/2}, |
|
{label:"MERCATOR",color:"steelblue", label_x:cv_width/2.8, label_y:cv_height/9} |
|
]; // labels and positions |
|
|
|
var g = svgAlMrCmp.selectAll("g") |
|
.data(projections) |
|
.enter() |
|
.append("g") |
|
.attr("transform", (d,i)=> `translate(${(i*cv_width/2)},0)` ) |
|
; // split canvas |
|
|
|
|
|
d3.json("world.topojson").then(function(world) { |
|
|
|
var brazil = topojson.feature( world,world.objects.countries ).features[210]; |
|
|
|
projections.forEach( |
|
proj => proj.fitExtent( |
|
[ [cv_margin,cv_margin], [cv_width/2-cv_margin, cv_width/2-cv_margin] ], |
|
brazil |
|
) |
|
); |
|
|
|
g.append("path") |
|
.attr("d", d=> d3.geoPath(d)(brazil) ) |
|
.attr("fill","none") |
|
.attr("stroke", (d,i) => projLayout[i].color ) |
|
.attr("stroke-width",1) |
|
; |
|
g.transition() |
|
.delay(2000) |
|
.duration(2000) |
|
.attr("transform","translate("+cv_width/4+",0)") |
|
; |
|
g.append("text") |
|
.text( (d,i) => projLayout[i].label ) |
|
.attr("x", (d,i) => projLayout[i].label_x ) |
|
.attr("y", (d,i) => projLayout[i].label_y ) |
|
.attr("fill", (d,i) => projLayout[i].color ) |
|
.style("font-size",fontSize).style("font-weight","bold") |
|
; |
|
}); |
|
|
|
} // \runAlMrCmp |
|
|
|
|
|
function ONLOAD() { |
|
svg1 = d3.select("#br-albers") |
|
.attr("width", canvas_width) |
|
.attr("height", height); |
|
svg2 = d3.select("#br-mercator") |
|
.attr("width", canvas_width) |
|
.attr("height", height); |
|
|
|
g1 = svg1.append("g") |
|
g2 = svg2.append("g") |
|
|
|
const trlte_shift = [canvas_width/71,canvas_width/28.8]; |
|
var projection1 = d3.geoConicEqualArea() |
|
.parallels([-2,-22]) |
|
.center([0,-12]) |
|
.rotate([54,0]) |
|
.scale(canvas_width*1.414930556) |
|
.translate([ canvas_width/2.0 - trlte_shift[0], height/2.0 - trlte_shift[1] ]); |
|
|
|
var projection2 = d3.geoMercator() |
|
.scale(canvas_width*1.414930556) |
|
.center([-52, -15]) |
|
.translate([canvas_width/2 + trlte_shift[0]*3, canvas_width/2 + trlte_shift[0]*6]); // + 18, 20 |
|
|
|
path1 = d3.geoPath().projection(projection1); |
|
path2 = d3.geoPath().projection(projection2); |
|
|
|
d3.json("./br-states.json").then(ready); // apply path1 and path2 |
|
|
|
d3.select(self.frameElement).style("height", height + "px"); // really need this line? |
|
|
|
g1.append("rect") // the canvas frame1 |
|
.attr("x", 0 ).attr("y", 0 ) |
|
.attr("class","map_canvas") |
|
.attr("width",canvas_width).attr("height",height) |
|
; |
|
g2.append("rect") // the canvas frame2 |
|
.attr("x", 0 ).attr("y", 0 ) |
|
.attr("class","map_canvas") |
|
.attr("width",canvas_width).attr("height",height) |
|
; |
|
|
|
var rectsXY = [] |
|
for (let i=0; i<nX; i++) for(let j=0; j<nY; j++) |
|
rectsXY.push( {"x":cellWidth*i, "y":cellHeight*j} ); |
|
|
|
g1.selectAll().data( rectsXY ).enter().append("rect") // GRID |
|
.attr("x", d=>d.x).attr("y", d=>d.y ) |
|
.attr("class","map_gridCell") |
|
.attr("width",cellWidth).attr("height",cellHeight) |
|
; |
|
g2.selectAll().data( rectsXY ).enter().append("rect") // GRID |
|
.attr("x", d=>d.x).attr("y", d=>d.y ) |
|
.attr("class","map_gridCell") |
|
.attr("width",cellWidth).attr("height",cellHeight) |
|
; |
|
|
|
runAlMrCmp(); |
|
|
|
} // ONLOAD |
|
</script> |
|
|
|
</head> |
|
|
|
|
|
<body onload="ONLOAD()"> |
|
|
|
<section id="br-maps"> |
|
<h3>Brazilian Topojson Map: Albers vs Mercator on grid</h3> |
|
<p>Adapted from <a href="https://bl.ocks.org/ppKrauss/0c33364240e841fa23e78b21005f792c">bl.ocks.org/ppKrauss/0c333</a> |
|
and <a href="https://bl.ocks.org/Andrew-Reid/0ebddf4724a1658e43da01a5feff859b">bl.ocks.org/Andrew-Reid/0ebdd</a>. |
|
</p> |
|
<svg id="AlMrCmp"></svg> |
|
<table border="0"> |
|
<tr> |
|
<td>Alberts projection:<br/><svg id="br-albers"></td> |
|
<td> </td> |
|
<td>Mercator projection:<br/><svg id="br-mercator"></td> |
|
</tr> |
|
</table> |
|
</section> |
|
|
|
<hr/> |
|
<p align="center"> |
|
Brazilian's (IBGE) official Statistical Grid, that |
|
<a href="https://spatialreference.org/ref/sr-org/albers-conical-equal-area-brazil-sirgas-2000/">use Albers-BR-2000</a> |
|
<br/><img src="thumbnail.png"/> |
|
</p> |
|
|
|
</body> |
|
|
|
</html> |