d3.js - tipos - Inversión con escala ordinal.
tipos de escalas de medicion en investigacion (8)
De hecho, creo que no tiene sentido que no haya un método de inversión para las escalas ordinales, pero puede averiguarlo utilizando el método ordinal.range (), que le devolverá los valores de inicio para cada barra, y Método ordinal.rangeBand () para su anchura.
Ejemplo aquí: http://fiddle.jshell.net/dMpbh/2/
El código relevante es
.on("click", function(d,i) {
var xPos = d3.mouse(this)[0];
console.log("Clicked at " + xPos);
//console.log(imageScale.invert(xPos));
var leftEdges = imageScale.range();
var width = imageScale.rangeBand();
var j;
for(j=0; xPos > (leftEdges[j] + width); j++) {}
//do nothing, just increment j until case fails
console.log("Clicked on " + imageScale.domain()[j]);
});
¿Hay alguna manera de encontrar la inversión de la escala ordinal?
Estoy usando el valor de la cadena en el eje x, que está usando la escala ordinal y yo en el movimiento del mouse, quiero encontrar inversión con el eje x para encontrar qué cadena hay en la posición del mouse.
¿Hay alguna manera de encontrar esto?
var barLabels = dataset.map(function(datum) {
return datum.image;
});
console.log(barLabels);
var imageScale = d3.scale.ordinal()
.domain(barLabels)
.rangeRoundBands([0, w], 0.1);
// divides bands equally among total width, with 10% spacing.
console.log("imageScale....................");
console.log(imageScale.domain());
.
.
var xPos = d3.mouse(this)[0];
xScale.invert(xPos);
En el pasado, he invertido el dominio y el rango cuando esto es necesario.
> var a = d3.scale.linear().domain([0,100]).range([0, w]);
> var b = d3.scale.linear().domain([0,w]).range([0, 100]);
> b(a(5));
5
Sin embargo, con ordinal la respuesta no es tan simple. He comprobado la documentación y el código y no parece ser una forma sencilla. Comenzaría asignando los elementos del dominio y resolviendo los puntos de inicio y parada. Aquí hay un comienzo.
imageScale.domain().map(function(d){
return {
''item'':d,
''start'':imageScale(d)
};
})
Considere publicar su pregunta como una solicitud de función en https://github.com/mbostock/d3/issues?state=open en el caso
- Hay suficiente demanda para tal característica
- Que no he pasado por alto nada o que hay algo más oculto debajo de la documentación que ayudaría en este caso.
Entiendo por qué Mike Bostock puede ser reacio a incluir invert
en escalas ordinales ya que no puede devolver un valor verdadero singular. Sin embargo, aquí está mi versión de ello.
La función toma una posición y devuelve los datos que lo rodean. Tal vez voy a seguir con una versión de búsqueda binaria más tarde :-)
function ordinalInvert(pos, scale) {
var previous = null
var domain = scale.domain()
for(idx in domain) {
if(scale(datum[idx]) > pos) {
return [previous, datum[idx]];
}
previous = datum[idx];
}
return [previous, null];
}
Lo resolví construyendo una segunda escala lineal con el mismo dominio y rango, y luego invirtiendo en eso.
var scale = d3.scale.ordinal()
.domain(domain)
.range(range);
var continousScale = d3.scale.linear()
.domain(domain)
.range(range)
var data = _.map(range, function(i) {
return continousScale.invert(i);
});
Puede obtener fácilmente el índice / datos del objeto en la devolución de llamada
.on("click", function(d,i) {
console.log("Clicked on index = " + i);
console.log("Clicked on data = " + d);
// d == imageScale.domain()[1]
});
d es el propio valor invertido .
No es necesario utilizar obj.domain () [index].
Recientemente me encontré en la misma situación que OP.
Necesitaba obtener el inverso de una escala categórica para un control deslizante. El control deslizante tiene 3 valores discretos y se ve y se comporta como un conmutador de tres posiciones. Cambia el modo de fusión en algunos elementos SVG. scaleQuantize()
una escala inversa con scaleQuantize()
siguiente manera:
var modeArray = ["normal", "multiply", "screen"];
var modeScale = d3.scalePoint()
.domain(modeArray)
.range([0, 120]);
var inverseModeScale = d3.scaleQuantize()
.domain(modeScale.range())
.range(modeScale.domain());
inverseModeScale
este modo inverseModeScale
la posición x del ratón ( d3.mouse(this)[0]
) al arrastrar:
.call( d3.drag()
.on("start.interrupt", function() { modeSlider.interrupt(); })
.on("start drag", function() { inverseModeScale(d3.mouse(this)[0]); })
)
Devuelve el elemento de modeArray
que está más cerca de la posición x del mouse. Incluso si ese valor está fuera de los límites (-400 o 940), devuelve el elemento correcto.
La respuesta puede parecer un poco específica a los controles deslizantes, pero la publicación de todos modos porque es válida (creo) y esta pregunta se encuentra en los mejores resultados para " d3 invert ordinal " en Google.
Nota: Esta respuesta utiliza d3 v4.
Si solo quiere saber qué posición del mouse corresponde a qué datos, entonces d3 ya lo está haciendo por usted.
.on("click", function(d,i) {
console.log("Clicked on " + d);
});
He actualizado el Fiddle de @AmeliaBR http://fiddle.jshell.net/dMpbh/17/