Public
Edited
May 2
Insert cell
Insert cell
Insert cell
circlesData = [
{ x: 50, y: 50, color: 'red' },
{ x: 100, y: 100, color: 'blue' },
{ x: 150, y: 150, color: 'green' },
]
Insert cell
Insert cell
{
// crear elemento SVG externo con tamaño 200x200
const width = 200;
const height = 200;
const radius = 10;
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height);
// agregar un fondo
svg.append('rect')
.attr('width', 200)
.attr('height', 200)
.attr('fill', '#F2ECF3');
// crear un círculo por cada elemento en circlesData
// y definir su posición, color y tamaño
const circles = svg.selectAll('circle')
// copiar los datos para no modificar los objetos originales
.data(circlesData.map(d => ({...d})))
.join('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('fill', d => d.color)
.attr('r', radius);
// nuevo código para arrastrar
// cuando comienza el arrastre
function onDragStart_0(event, d) {
d3.select(this)
// hacer que el círculo arrastrado aparezca encima
// de otros círculos sobre los que se mueve
.raise()
.attr('fill', 'yellow')
.attr('stroke', 'black');
}
// mientras el arrastre está en progreso
function onDrag_0(event, d) {
d.x = event.x;
d3.select(this)
.attr('cx', d.x)
.attr('cy', d.y = event.y);
}
// cuando termina el arrastre
function onDragEnd_0(event, d) {
d3.select(this)
.attr('fill', d.color)
.attr('stroke', 'none');
}
const drag = d3.drag()
.on('start', onDragStart_0)
.on('drag', onDrag_0)
.on('end', onDragEnd_0);
circles.call(drag);
return svg.node();
}

Insert cell
Insert cell
{
const width = 200;
const height = 200;
const circleRadius = 10;
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height);
svg.append('rect')
.attr('width', 200)
.attr('height', 200)
.attr('fill', '#F2ECF3');
const circles = svg.selectAll('circle')
.data(circlesData.map(d => ({...d})))
.join('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('fill', d => d.color)
.attr('r', circleRadius);
function onDragStart_1(event, d) {
d3.select(this)
.raise()
.attr('fill', 'yellow')
.attr('stroke', 'black');
}
function onDrag_1(event, d) {
d3.select(this)
.attr('cx', event.x)
.attr('cy', event.y);
}
function onDragEnd_1(event, d) {
d3.select(this)
.attr('fill', d.color)
.attr('stroke', 'none');
}
const drag = d3.drag()
.on('start', onDragStart_1)
.on('drag', onDrag_1)
.on('end', onDragEnd_1);
circles.call(drag);
return svg.node();
}

Insert cell
Insert cell
{
const width = 200;
const height = 200;
const radius = 10;
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height);
svg.append('rect')
.attr('width', 200)
.attr('height', 200)
.attr('fill', '#F2ECF3');
const circles = svg.selectAll('circle')
.data(circlesData)
.join('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('fill', d => d.color)
.attr('r', radius);

circles.call(circleDrag_2_2(width, height, radius));
return svg.node();
}
Insert cell
function circleDrag_2_2(width, height, radius) {
function onDragStart_2(event, d) {
d3.select(this)
.raise()
.attr('fill', 'yellow')
.attr('stroke', 'black');
}
function onDrag_2(event, d) {
const x = Math.max(radius, Math.min(width - radius, event.x));
const y = Math.max(radius, Math.min(height - radius, event.y));
d3.select(this)
.attr('cx', d.x = x)
.attr('cy', d.y = y);
}
function onDragEnd_2(event, d) {
d3.select(this)
.attr('fill', d.color)
.attr('stroke', 'none');
}
const drag = d3.drag()
.on('start', onDragStart_2)
.on('drag', onDrag_2)
.on('end', onDragEnd_2);
return drag;
}
Insert cell
Insert cell
function circleDrag_3(width, height, radius, svg) {
function onDragStart_22(event, d) {
d3.select(this)
.raise()
.attr('fill', 'yellow')
.attr('stroke', 'black');
d.tooltip = svg.append("text")
.attr("x", d.x)
.attr("y", d.y)
.attr("font-size", "15px")
.attr("fill", "black")
.text(`(${Math.round(d.x)}, ${Math.round(d.y)})`);
}

function onDrag_2_22(event, d) {
const x = Math.max(radius, Math.min(width - radius, event.x));
const y = Math.max(radius, Math.min(height - radius, event.y));

d.x = x;
d.y = y;

d3.select(this)
.attr('cx', x)
.attr('cy', y);

if (d.tooltip) {
d.tooltip
.attr("x", x + radius + 5)
.attr("y", y)
.text(`(${Math.round(x)}, ${Math.round(y)})`);
}
}

function onDragEnd_2_22(event, d) {
d3.select(this)
.attr('fill', d.color)
.attr('stroke', 'none');

if (d.tooltip) {
d.tooltip.remove();
d.tooltip = null;
}
}

return d3.drag()
.on('start', onDragStart_22)
.on('drag', onDrag_2_22)
.on('end', onDragEnd_2_22);
}

Insert cell
{
const width = 200;
const height = 200;
const radius = 10;

const svg = d3.create('svg')
.attr('width', width)
.attr('height', height);

svg.append('rect')
.attr('width', width)
.attr('height', height)
.attr('fill', '#F2ECF3');

const circles = svg.selectAll('circle')
.data(circlesData)
.join('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('fill', d => d.color)
.attr('r', radius);

circles.call(circleDrag_3(width, height, radius, svg));

return svg.node();
}

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