Unlisted
Edited
Oct 6, 2023
1 fork
Insert cell
Insert cell
Insert cell
mutable gaLoaded = false;
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
baseMapSVG = {
const svg = d3.create("svg").attr("viewBox", `0 0 ${baseWidth} ${baseHeight}`);
const entLayer = svg
.append("g")
.attr("id", "ent")
.append("path")
.attr("d", cached_ent_path)
.attr("fill", "#f5f5f5")
.attr("stroke", "#999")
.attr("stroke-width", 1.2);

const circlesLayer = svg
.append("g")
.attr("id", "all-fosas")
.selectAll("circle")
.data(mun_fosas)
.join("circle")
.attr("id", (d) => `${d.CVEGEO}-${d.ANIO}`)
.attr("class", (d) => `fosas-circle fosas-circle-${d.ANIO}`)
.attr("cx", (d) => projection(d.geometry.coordinates)[0])
.attr("cy", (d) => projection(d.geometry.coordinates)[1])
.attr("r", (d) => dotScale(d.rolling))
.attr("stroke", "#fff")
.attr("stroke-width", 0)
.attr("fill", (d) => yearScale(d.ANIO))
.attr("fill-opacity", 1)
.attr("data-cvegeo", (d) => d.CVEGEO);

const labelsLayer = svg
.append("g")
.attr("id", "ent-label")
.selectAll("text")
.data(ent.features)
.join("text")
.text((d) => {
const abbrev = ent_abbrev.get(d.properties.CVEGEO);
return abbrev ? abbrev : "";
})
.attr("id", d => `ent-cve-${d.properties.CVEGEO}`)
.attr("text-anchor", "middle")
.attr("x", (d) => path.centroid(d)[0])
.attr("y", (d) => path.centroid(d)[1])
.attr("stroke-width", 2)
.attr("fill", "#999")
.attr("stroke", "#fff")
.attr("paint-order", "stroke");

const tooltipsLayer = svg.append("g").attr("id", "tooltips");

const dotLegend = svg.append("g");

const dotY = 400;
const textOffset = 35;
const lineHeight = 25;
dotLegend
.append("circle")
.attr("r", dotScale(maxSum))
.attr("fill", "none")
.attr("stroke", "#999")
.attr("stroke-width", 1.5)
.attr("cx", dotScale(maxSum) + 1)
.attr("cy", dotY);

dotLegend
.append("circle")
.attr("r", dotScale(10))
.attr("fill", "none")
.attr("stroke", "#999")
.attr("stroke-width", 1.5)
.attr("cx", dotScale(maxSum) + 1)
.attr("cy", dotY + dotScale(maxSum) - dotScale(10));

dotLegend
.append("text")
.text("10 fosas")
.attr("x", dotScale(maxSum) * 2 + 5)
.attr("y", dotY + dotScale(maxSum))
.attr("text-anchor", "start")
.attr("class", "circle-legend-text")

dotLegend
.append("text")
.text(`${maxSum} fosas`)
.attr("x", dotScale(maxSum) * 2 + 5)
.attr("y", dotY - dotScale(maxSum) + 12)
.attr("text-anchor", "start")
.attr("class", "circle-legend-text")

dotLegend.append("text").text("El tamaño de cada punto")
.attr("x", 0)
.attr("y", dotY + dotScale(maxSum) + textOffset)
.attr("text-anchor", "start")
.attr("class", "circle-legend-note");

dotLegend.append("text").text("representa el número de")
.attr("x", 0)
.attr("y", dotY + dotScale(maxSum) + textOffset + lineHeight)
.attr("text-anchor", "start")
.attr("class", "circle-legend-note");

dotLegend.append("text").text("fosas clandestinas encontradas")
.attr("x", 0)
.attr("y", dotY + dotScale(maxSum) + textOffset + (lineHeight * 2))
.attr("text-anchor", "start")
.attr("class", "circle-legend-note");

dotLegend.append("text").text("en cada municipio.")
.attr("x", 0)
.attr("y", dotY + dotScale(maxSum) + textOffset + (lineHeight * 3))
.attr("text-anchor", "start")
.attr("class", "circle-legend-note");


const sourceLine = svg.append("g");
sourceLine.append("text").text("Fuente: Comisión Nacional de Búsqueda.")
.attr("x", baseWidth)
.attr("y", baseHeight - 28)
.attr("text-anchor", "end")
.attr("class", "map-sourceline");

sourceLine.append("text").text("Datos al 30 de abril, 2023.")
.attr("x", baseWidth)
.attr("y", baseHeight - 4)
.attr("text-anchor", "end")
.attr("class", "map-sourceline");
const logoWidth = 250;
const elabLogoAspect = .21875;
svg.append("svg:image")
.attr("xlink:href", d => elab_logo_color)
.attr("x", baseWidth - logoWidth)
.attr("y", 0)
.attr("width", logoWidth)
.attr("height", logoWidth * elabLogoAspect);

const adondeAspect = .45625;
svg.append("svg:image")
.attr("xlink:href", d => logoAdondevanlosdesaparecidos)
.attr("x", baseWidth - logoWidth)
.attr("y", 50)
.attr("width", logoWidth)
.attr("height", logoWidth * adondeAspect);
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mapStyle = html`
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600&display=swap" rel="stylesheet">
<link href="https://unpkg.com/tippy.js@3/dist/themes/light-border.css" rel="stylesheet" />
<style>
.fosas-play-controls {
margin-bottom: 1.2em;
}
.fosas-play-controls button {
border-radius: 7px;
border: none;
padding: 3px 5px;
}
.fosas-play-controls input {
accent-color: #0057ae;
}
.tippy-popper {
z-index: 999999 !important;
}
.tippy-content {
text-align: left;
padding-left: .5em;
padding-right: .5em;
max-width: 200px;
}
.tippy-content p, .tippy-content h3, .tippy-content table {
font-family: "Open Sans", "Helvetica Neue", Helvetica, sans serif;
}
.tippy-content h3 {
font-size: 1.15em;
margin-top: .5em;
margin-bottom: .5em;
}
.tippy-content tr.all-time td {
font-weight: 600;
}
.tippy-content td {
vertical-align: baseline;
}
.tippy-content td.label {
font-size: .9em;
text-align: left;
white-space: nowrap;
}
.tippy-content td.years {
font-size: .8em;
width: 100%;
padding-left: 8px;
}
.tippy-content table {
margin: .5em 0;
max-width: 200px;
width: 100%;
}
.tippy-content svg {
margin-top: 1em;
}
#ent-label text {
font-family: "Open Sans", "Helvetica Neue", sans serif;
text-transform: uppercase;
font-weight: 600;
letter-spacing: -0.05px;
font-size: 17px;
}
.circle-legend-text {
font-family: "Open Sans", "Helvetica Neue", sans serif;
font-size: 17px;
font-weight: 400;
}
.circle-legend-note, .map-sourceline {
font-family: "Open Sans", "Helvetica Neue", sans serif;
font-size: 14px;
font-weight: 400;
fill: #666;
}
.fosas-year-legend {
margin-top: -50px;
}
@media only screen and (max-width: 768px) {
.circle-legend-text {
font-size: 23px;
}
.circle-legend-note, .map-sourceline {
font-size: 21px;
}
#ent-label text {
font-size: 24px;
}
#ent-cve-01, #ent-cve-11, #ent-cve-12, #ent-cve-13, #ent-cve-16, #ent-cve-17, #ent-cve-18, #ent-cve-21, #ent-cve-24, #ent-cve-27 { display: none; }
}
</style>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Inputs.table(mun_fosas)
Insert cell
Insert cell
Inputs.table(fosas_no_year)
Insert cell
fosas_no_year = fosas_data.filter(d => !d.ANIO && d.CVEGEO !== "NA").groupby("CVEGEO").rollup({ TOTAL_FOSAS: d => aq.op.sum(d.TOTAL_FOSAS)}).derive({ANIO: d => null}).orderby(aq.desc("TOTAL_FOSAS"))
Insert cell
fosas_no_year_total = fosas_no_year.rollup({sum: aq.op.sum("TOTAL_FOSAS")}).get("sum", 0)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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