Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

306
Vistas
Is it possible to not reorder elements when using d3.join?

In d3, we may change the order of elements in a selection, for example by using raise.

Yet, when we rebind the data and use join, this order is discarded.

This does not happen when we use "the old way" of binding data, using enter and merge.

See following fiddle where you can click a circle (for example the blue one) to bring it to front. When you click "redraw", the circles go back to their original z-ordering when using join, but not when using enter and merge.

Can I achive that the circles keep their z-ordering and still use join?

const data = [{
  id: 1,
  v: 10,
  c: 'red'
}, {
  id: 2,
  v: 30,
  c: 'blue'
}, {
  id: 3,
  v: 60,
  c: 'green'
}]

let nDrawCall = 0

function redraw() {
  nDrawCall++
  //svg1 with old enter-merge pattern that works
  const circles = d3.select('#svg1')
    .selectAll('circle')
    .data(data, d => d.id)
  circles
    .enter()
    .append('circle')
    .on('click', function() {
      d3.select(this).raise()
    })
    .merge(circles)
    .attr('cx', d => d.v * nDrawCall)
    .attr('cy', d => d.v)
    .attr('r', d => d.v)
    .attr('fill', d => d.c)
    
  //svg2 with new join pattern that sadly reorders
  d3.select('#svg2')
    .selectAll('circle')
    .data(data, d => d.id)
    .join(enter => enter
      .append('circle')
      .on('click', function() {
        d3.select(this).raise()
      })
    )
    .attr('cx', d => d.v * nDrawCall)
    .attr('cy', d => d.v)
    .attr('r', d => d.v)
    .attr('fill', d => d.c)
}

function reset() {
  nDrawCall = 0
  redraw()
}

redraw()

/*
while (true) {
  iter++
  console.log(iter)
  sleepFor(500)
}
*/
svg {
  height: 100px;
  width: 100%;
}
<html>
  <head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
  </head>
  <body>
    <button onclick="redraw()">
      Redraw
    </button>
    <button onclick="reset()">
      Reset
    </button>
    <div>
      <svg id="svg1" />  
      <svg id="svg2" />
    </div>
  </body>

</html>

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

join does an implicit order after merging the enter- and update-selection, see https://github.com/d3/d3-selection/blob/91245ee124ec4dd491e498ecbdc9679d75332b49/src/selection/join.js#L14.

The selection order after the data binding in your example is still red, blue, green even if the document order is changed. So the circles are reordered to the original order using join.

You can get around that by changing the data binding reflecting the change in the document order. I did that here, by moving the datum of the clicked circle to the end of the data array.

let data = [{
  id: 1,
  v: 10,
  c: 'red'
}, {
  id: 2,
  v: 30,
  c: 'blue'
}, {
  id: 3,
  v: 60,
  c: 'green'
}]

let nDrawCall = 0

function redraw() {
  nDrawCall++
  d3.select('#svg2')
    .selectAll('circle')
    .data(data, d => d.id)
    .join(enter => enter
      .append('circle')
      .on('click', function() {
        const circle = d3.select(this).raise();
        data.push(data.splice(data.indexOf(circle.datum()), 1)[0]);
      })
    )
    .attr('cx', d => d.v * nDrawCall)
    .attr('cy', d => d.v)
    .attr('r', d => d.v)
    .attr('fill', d => d.c)
}

function reset() {
  nDrawCall = 0
  redraw()
}

redraw()
svg {
  height: 100px;
  width: 100%;
}
<html>
  <head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
  </head>
  <body>
    <button onclick="redraw()">
      Redraw
    </button>
    <button onclick="reset()">
      Reset
    </button>
    <div>
      <svg id="svg2" />
    </div>
  </body>

</html>

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda