Public
Edited
Apr 26, 2023
1 fork
1 star
Insert cell
Insert cell
// Generamos 500 puntos 2d con media 0 y sigma proporcional al ancho y alto de la gráfica
data = d3.range(0,500).map(d => ({
x: d3.randomNormal(0, width/8)(),
y: d3.randomNormal(0, height/8)()
}))
Insert cell
Insert cell
chart = {

// 1. Escalas
const xScale = d3.scaleLinear([ -width/2, width/2 ], [ -width/2, width/2 ])
const yScale = d3.scaleLinear([ -height/2, height/2 ], [ -height/2, height/2 ])
// 2. Canvas
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height)
.property("value", []);
// 3. Vamos a crear los componentes gráficos dentro de un contenedor <g> centrado
const contenedor = svg.append('g')
.attr('class', 'container')
.attr('transform', `translate(${ width/2 },${ height/2 })`)
// 4. Creamos los puntos
const points = contenedor.selectAll('circle.point')
.data(data)
.enter()
.append('circle')
.attr('class', 'point')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', 8)
.style('fill', color)
.style('opacity', 0.8)
// 5. Ejes
const xAxis = d3.axisBottom(xScale)
contenedor.append('g').call(xAxis)
const yAxis = d3.axisLeft(yScale)
contenedor.append('g').call(yAxis)
// 6. Removemos el texto de los ejes
contenedor.selectAll('.tick text').remove()
return svg.node()
}
Insert cell
Insert cell
brush = d3.brush()
.extent([ [ -width/2, -width/2 ], [ width/2, width/2] ])
.on('start', brushStart)
.on('brush', brushing)
Insert cell
Insert cell
brushStart = function() {
// Selecciono todos los circulos de la grafica
const points = d3.select(chart).selectAll('circle.point')
// Les seteo el color con la paleta color (definida más abajo)
points.style('fill', color)
}
Insert cell
Insert cell
brushing = function() {
// Obtenemos el bounding-box de la selección.
// Tiene las coordeandas superior-izquierda e inferior-derecha de la selección
// en este formato [[coordenada superior-izquierda ], [coordenada inferior-derecha ]]
const selection = d3.event.selection
// Seleccionamos todos los puntos de nuetra gráfica
const points = d3.select(chart).selectAll('circle.point')
// Si la selección es nula, debemos ver los puntos con los colores originales
if( selection === null ) {
points.style('fill', color)
}
// Si no es nula...
else
{
// Coordenadas de la selección: x_min, x_max, y_min, y_max
const x_min = selection[0][0] // x más a la izquierda
const x_max = selection[1][0] // x más a la derecha
const y_min = selection[0][1] // y más arriba
const y_max = selection[1][1] // y más abajo
// Le cambiamos el color a los puntos en base a si se encuentran
// dentro o fuera del área de selección.
points.style('fill', function(d) {
// Si la coordenada x del punto es mayor a la coordenada x_min de la selección
// y menor a la coordenada x_max de la selección, entonces está en el rango x de la selección
const inRangeX = d.x >= x_min && d.x < x_max
// Si la coordeanada y del punto es mayor a la coordeanda y_min de la selección
// y menor a la coordenada y_max de la selección, entonces está en el rango y de la selección
const inRangeY = d.y >= y_min && d.y < y_max
// Si está en el rango x y en el rango y, entonces está seleccionada
if(inRangeX && inRangeY) {
// La pintamos del color original
return color(d)
} else {
// Sino, está fuera de la selección, la pintamos de gris
return 'gray'
}
})
}
}
Insert cell
Insert cell
d3.select( chart )
.select('g.container')
.call(brush)
Insert cell
Insert cell
Insert cell
height = 500
Insert cell
color = (d) => d3.interpolateRainbow( Math.hypot(d.x, d.y) / Math.hypot(width/4, width/4) )
Insert cell
d3 = require('d3@5')
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more