2012-09-07 27 views
18

Al trabajar en D3.js, me gustaría seleccionar todos los elementos que coincidan con un selector excepto para el elemento actual.¿Equivalente del selector 'no' de jQuery en D3.js?

La razón es que me gustaría alternar un círculo, y hacer que todos los demás círculos con la misma clase se vuelvan de color azul claro, pero el círculo actual permanezca con el mismo tono.

Esto es lo que tengo actualmente:

vis.selectAll('circle.prospect') 
.on("mouseover", function(d) { 
    console.log(d); 
    d3.selectAll('circle.prospect').transition().style('opacity','0.5'); 
    d3.select(this).attr('opacity','1.0'); 
    }); 

En jQuery, me could do this using not. ¿Alguien sabe el equivalente de D3.js?

+2

has probado 'd3.selectAll ('circle.prospect: not (this)')'? –

+0

@ZoltanToth - sí, eso no funciona, me temo. – Richard

+1

También puede usar CSS simple para esto, en lugar de JavaScript. Por ejemplo, para atenuar los otros círculos cuando se desplaza sobre cualquier círculo en el elemento SVG externo: 'svg: hover circle: not (: hover) {opacity: .5; } ' – mbostock

Respuesta

14

Una forma aún más simple de abordar esto sería usar el poder de los operadores de D3:

vis.selectAll('circle.prospect').on("mouseover", function(d) { 
    var circleUnderMouse = this; 
    d3.selectAll('circle.prospect').transition().style('opacity',function() { 
     return (this === circleUnderMouse) ? 1.0 : 0.5; 
    }); 
}); 

Hay una diferencia en este caso en que, a diferencia de su código original, la opacidad del elemento circleUnderMouse será animado sin problemas también. Si ya es completamente opaco, probablemente no sea un gran problema, de lo contrario, podría usar el operador .duration() de una manera similar para acelerar el tiempo circleUnderMouse a 0 y los otros más.

17

Puede filter una selección:

vis.selectAll('circle.prospect') 
.on("mouseover", function(d) { 
    console.log(d); 
    var circleUnderMouse = this; 
    d3.selectAll('circle.prospect').filter(function(d,i) { 
     return (this !== circleUnderMouse); 
    }).transition().style('opacity','0.5'); 
    d3.select(this).attr('opacity','1.0'); 
    }); 
20

Si los elementos tienen una identificadores únicos CSS-accesible, que puede utilizar el selector de :not(). Algunos ejemplos posibles:

d3.selectAll("circle.prospect:not(#" + this.id + ")"); 
d3.selectAll("circle.prospect:not(." + someUniqueClassFrom(d) + ")"); 
d3.selectAll("circle.prospect:not([uniqueAttr=" + this.getAttribute('uniqueAttr') + "])"); 

La razón d3.selectAll('circle.prospect:not(this)') que no funciona es porque es sólo literalmente, diciendo que se corten las <this></this> elementos - que obviamente no es su intención, y puesto que ya está seleccionando sólo <circle></circle> elementos tendrían ningún efecto independientemente.

Incluso si no se aplican generalmente algún atributo DOM único, no hay ninguna razón por la que no se podía establecer una forma temporal:

vis.selectAll('circle.prospect') 
.on("mouseover", function(d) { 
    this.id = 'temp-' + Math.random(); 
    d3.selectAll('circle.prospect:not(#' + this.id + ')').transition().style('opacity','0.5'); 
    d3.select(this).attr('opacity','1.0'); 
    this.id = ''; 
    }); 

Dicho esto, sin embargo, si sus elementos no tienen ya un ID asignado ya, creo que la solución de Ian Roberts es probablemente lo que yo haría en lugar de este hack de identificador temporal.

+0

mejor respuesta con el no selector ... – Juan