Public
Edited
Apr 28
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
departamentos = FileAttachment("departamentos-buenos_aires.json").json()
Insert cell
departamentos.features[0]
Insert cell
departamentos.features.filter(d => d.properties.departamento === "TRES DE FEBRERO")
Insert cell
tresDeFebrero = ({
type: "FeatureCollection",
features: departamentos.features.filter(
d => d.properties.departamento === "TRES DE FEBRERO"
)
})
Insert cell
Insert cell
{
const container = yield htl.html`<div style="height: 500px;">`;
const map = L.map(container);
const layer = L.geoJSON(tresDeFebrero).addTo(map);
map.fitBounds(layer.getBounds(), {maxZoom: 9});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "© <a href=https://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
}).addTo(map);
}
Insert cell
Plot.plot({ projection: "equal-earth", marks: [Plot.geo(tresDeFebrero)] })
Insert cell
mapaTresDeFebrero = {
const width = 600;
const height = 600;

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("border", "1px solid #ccc");

const projection = d3.geoMercator()
.fitSize([width, height], tresDeFebrero);

const pathGenerator = d3.geoPath().projection(projection);

svg.append("path")
.datum(tresDeFebrero.features[0]) // le damos un único objeto GeoJSON (el Feature)
.attr("d", pathGenerator) // el atributo "d" es el camino generado
.attr("fill", "rgba(173, 216, 230, 0.5)") // color de relleno
.attr("stroke", "black") // color del borde
.attr("stroke-width", 1);
return svg.node();
}
Insert cell
mapaFondo = {
const width = 400;
const height = 400;
const zoom = 13;

// Coordenadas de Caseros, Tres de Febrero
const lon = -58.5638;
const lat = -34.6037;

// Función para convertir (lon, lat) a (tileX, tileY)
function lonLatToTile(lon, lat, zoom) {
const x = Math.floor((lon + 180) / 360 * Math.pow(2, zoom));
const y = Math.floor((1 - Math.log(Math.tan(lat * Math.PI/180) + 1 / Math.cos(lat * Math.PI/180)) / Math.PI) / 2 * Math.pow(2, zoom));
return [x, y];
}

const [tileX, tileY] = lonLatToTile(lon, lat, zoom);

console.log(`Tile X: ${tileX}, Tile Y: ${tileY}, Zoom: ${zoom}`);

// Crear contenedor
const container = d3.create("div")
.style("position", "relative")
.style("width", `${width}px`)
.style("height", `${height}px`)
.style("border", "1px solid #ccc");

// Agregar imagen de fondo
container.append("img")
.attr("src", `https://tile.openstreetmap.org/${zoom}/${tileX}/${tileY}.png`)
.style("position", "absolute")
.style("width", "100%")
.style("height", "100%")
.style("object-fit", "cover");

return container.node();
}
Insert cell
mapaCompleto = {
const width = 300;
const height = 300;
const zoom = 14;

const lon = -58.5638;
const lat = -34.6037;

function lonLatToTile(lon, lat, zoom) {
const x = Math.floor((lon + 180) / 360 * Math.pow(2, zoom));
const y = Math.floor((1 - Math.log(Math.tan(lat * Math.PI/180) + 1 / Math.cos(lat * Math.PI/180)) / Math.PI) / 2 * Math.pow(2, zoom));
return [x, y];
}

const [tileX, tileY] = lonLatToTile(lon, lat, zoom);

const container = d3.create("div")
.style("position", "relative")
.style("width", `${width}px`)
.style("height", `${height}px`)
.style("border", "1px solid #ccc");

container.append("img")
.attr("src", `https://tile.openstreetmap.org/${zoom}/${tileX}/${tileY}.png`)
.style("position", "absolute")
.style("width", "100%")
.style("height", "100%")
.style("object-fit", "cover");

const svg = container.append("svg")
.attr("width", width)
.attr("height", height)
.style("position", "absolute")
.style("top", 0)
.style("left", 0);

// ¡Atención aquí!
const projection = d3.geoMercator()
.fitExtent([[0, 0], [width, height]], tresDeFebrero);

const pathGenerator = d3.geoPath()
.projection(projection);

svg.append("path")
.datum(tresDeFebrero.features[0])
.attr("d", pathGenerator)
.attr("fill", "rgba(173, 216, 230, 0.3)")
.attr("stroke", "black")
.attr("stroke-width", 1);

return container.node();
}
Insert cell
mapaTresDeFebrero2 = {
const width = 600;
const height = 600;

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("border", "1px solid #ccc");

const projection = d3.geoMercator()
.fitSize([width, height], tresDeFebrero);

const pathGenerator = d3.geoPath().projection(projection);

svg.append("path")
.datum(tresDeFebrero.features[0]) // le damos un único objeto GeoJSON (el Feature)
.attr("d", pathGenerator) // el atributo "d" es el camino generado
.attr("fill", "rgba(173, 216, 230, 0.5)") // color de relleno
.attr("stroke", "black") // color del borde
.attr("stroke-width", 1);
return svg.node();
}
Insert cell
Insert cell
sentimientosData = FileAttachment("3f_vecinal1_government_q8_answer_sentiment_analysis_SAMPLE.json").json()
Insert cell
mapaTresDeFebrero3 = {
const width = 600;
const height = 600;

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("border", "1px solid #ccc");

const projection = d3.geoMercator()
.fitSize([width, height], tresDeFebrero);

const pathGenerator = d3.geoPath().projection(projection);

svg.append("path")
.datum(tresDeFebrero.features[0]) // le damos un único objeto GeoJSON (el Feature)
.attr("d", pathGenerator) // el atributo "d" es el camino generado
.attr("fill", "rgba(173, 216, 230, 0.5)") // color de relleno
.attr("stroke", "black") // color del borde
.attr("stroke-width", 1);

const colorSentimiento = sentiment => {
switch(sentiment) {
case 'POS': return "green";
case 'NEG': return "red";
case 'NEU': return "orange";
default: return "gray";
}
};
const radioSentimiento = score => {
return 2 + score * 12; // Radio mínimo 2px, máximo 10px (ajustable)
};

const escalaRadio = d3.scaleLinear()
.domain([0, 1])
.range([2, 10]);
svg.selectAll("circle")
.data(sentimientosData)
.enter()
.append("circle")
.attr("cx", d => projection([d.lng, d.lat])[0])
.attr("cy", d => projection([d.lng, d.lat])[1])
.attr("r", d => radioSentimiento(d.sentiment_score))
.attr("opacity", 0.6)
.attr("stroke", "#555")
.attr("stroke-width", 0.8)
.attr("fill", d => colorSentimiento(d.sentiment))
.append("title")
.text(d => `${d.city}\nedad ${d.age} años\nsexo ${d.sex}\n\n"${d.text}"`);

return svg.node();
}
Insert cell
Insert cell
Insert cell
proyeccion = d3.geoMercator()
.center([-64, -38]) // Centro aproximado de Argentina
.scale(1000) // Escala para encuadrar el país
.translate([400, 500]) // Posiciona el centro del mapa en tu SVG
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