D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
dlimasouza
Full window
Github gist
Force-directed cartogram
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="https://unpkg.com/topojson@3"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } </style> </head> <body> <div id="mapa" style="position: relative;left: 0; top: 0;"> <canvas id='mapa_base' style="position: absolute; left: 0; top: 0; z-index: 0;border: 2px solid green"></canvas> <canvas id='mapa_bolhas' style="position: absolute; left: 0; top: 0; z-index: 1;border: 1px solid red"></canvas> </div> <script> const width = 800; const height = 800; const canvas_bolhas = d3.select("#mapa_bolhas") .attr("width", width) .attr("height", height); const canvasBase = d3.select("#mapa_base") .attr("width", width) .attr("height", height); const baseMapa = canvasBase.node().getContext("2d") const context = canvas_bolhas.node().getContext("2d"); /*var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) */ const promises = [d3.json('municipios.json'), d3.json('estados.json')]; Promise.all(promises).then((values) => { const municipios = values[0]; const estados = values[1]; //const rio = municipios.filter(d => d.uf === "RJ") const rio = municipios.filter(d => d) const rio_base = topojson.feature(estados, estados.objects.BRUFE250GC_SIR); const rio_filtro = rio_base.features.filter(d=> d.properties.CD_GEOCUF == 33)[0] const extent = d3.extent(municipios, d=> d.pop2017) const maximo = extent[1] const escalaCor = d3.scaleLinear() const projecao = d3.geoMercator().fitSize([width, height], rio_base) const path = d3.geoPath().projection(projecao).context(baseMapa) //IMPORTANTE const tamanho = d3.scaleSqrt().domain(extent).range([1,20]) const cor = d3.scaleOrdinal().domain([1,2,3,4]).range(d3.schemeSet1) const simulacao = d3.forceSimulation() .force('center', d3.forceCenter(width / 2, height / 2)) .force('collision', d3.forceCollide(d => tamanho(d.pop2017)).iterations(2)) .force('x', d3.forceX(d => projecao([d.lon,d.lat])[0]).strength(0.3)) .force('y', d3.forceY(d => projecao([d.lon,d.lat])[1]).strength(0.3)) .nodes(rio) /*const base = canvas.selectAll('.base_UF') .data([null]) .enter() .append('path') .attr('class', 'base_UF') .attr('d', path(rio_base)) .style('fill', '#f2f2f2') */ function drawBase(ctx){ ctx.clearRect(0, 0, width, height); ctx.beginPath(); ctx.fillStyle = '#f2f2f2'; path(rio_base); ctx.fill(); ctx.closePath(); } /*const circulos = canvas.selectAll("circle.node") .data(municipios) .enter() .append("circle") .attr("class", "node") .attr('r', d => tamanho(d.pop2017)) .style('fill', d => cor(d.venc)) .style('stroke', 'red') .style("stroke-width", 0) circulos.append('title') .text(d => d.municipio) */ drawBase(baseMapa); simulacao.on("tick", ticked) function ticked(){ context.clearRect(0, 0, width, height); // draw nodes context.strokeStyle = "#fff"; context.lineWidth = 0.5; municipios.forEach(function(d, i) { context.beginPath(); context.fillStyle = cor(d.venc); context.moveTo(d.x, d.y); context.arc(d.x, d.y, tamanho(d.pop2017), 0, 2 * Math.PI); context.stroke(); context.fill(); context.closePath(); }); /*d3.selectAll("circle.node") .attr("cx", d => d.x) .attr("cy", d => d.y) */ } }) </script> </body>
https://d3js.org/d3.v5.min.js
https://unpkg.com/topojson@3