Подтвердить что ты не робот

Инверсия с порядковой шкалой

Есть ли способ найти инверсию порядковой шкалы?

Я использую строковое значение по оси х, которое использует порядковый масштаб и я на перемещении мыши. Я хочу найти инверсию с осью x, чтобы найти, какая строка находится в позиции мыши?

Есть ли способ найти это?

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);
4b9b3361

Ответ 1

Я действительно думаю, что не имеет смысла, что для порядковых масштабов нет метода инвертирования, но вы можете понять его с помощью метода ordinal.range(), который вернет вам начальные значения для каждого бара, и метод ordinal.rangeBand() для их ширины.

Пример здесь: http://fiddle.jshell.net/dMpbh/2/

Соответствующий код

    .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]);
    });

Ответ 2

Я нашел более короткую реализацию здесь в этом отклонил запрос на отрыв, который работал отлично.

var ypos = domain[d3.bisect(range, xpos) - 1];

где домен и диапазон - это масштабный домен и диапазон:

var domain = x.domain(),
    range = x.range();

Ответ 3

Я в прошлом менял домен и диапазон, когда это необходимо

> 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

Однако с порядковым ответом не так просто. Я проверил документацию и код, и это не похоже на простой способ. Я бы начал с отображения элементов из домена и разработки точки старта и остановки. Вот начало.

imageScale.domain().map(function(d){
    return {
        'item':d,
        'start':imageScale(d)
    };
})

Рассмотрите возможность размещения вашего вопроса в виде запроса функции https://github.com/mbostock/d3/issues?state=open в случае

  • Существует достаточный спрос на такую ​​функцию
  • Что я ничего не забыл или что что-то более скрытое ниже документации, которая поможет в этом случае

Ответ 4

Недавно я оказался в той же ситуации, что и OP.

Мне нужно было получить инверсию категориальной шкалы для слайдера. Ползунок имеет 3 дискретных значения и выглядит и ведет себя как трехходовой тумблер. Он изменяет режим смешивания на некоторых элементах SVG. Я создал обратную шкалу с scaleQuantize() следующим образом:

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 x-позицию мыши (d3.mouse(this)[0]) при перетаскивании:

.call( d3.drag()
    .on("start.interrupt", function() { modeSlider.interrupt(); })
    .on("start drag", function() { inverseModeScale(d3.mouse(this)[0]); })
)

Он возвращает элемент из modeArray, который ближе всего к x-позиции мыши. Даже если это значение выходит за пределы (-400 или 940), оно возвращает правильный элемент.

Ответ может показаться немного специфичным для слайдеров, но все равно, поскольку он действителен (я думаю), и этот вопрос находится в верхних результатах для "d3 инвертирования порядкового номера" в Google.

Примечание. В этом ответе используется d3 v4.

Ответ 5

Я понимаю, почему Майк Босток может неохотно включать invert в порядковые шкалы, так как вы не можете вернуть единственное истинное значение. Однако, вот моя версия.
Функция принимает позицию и возвращает окружающие данные. Возможно, я продолжу бинарную версию поиска позже: -)

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];
}

Ответ 6

Я решил его, построив вторую линейную шкалу с тем же доменом и диапазоном, а затем вызвал инверсию на этом.

  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);
  });

Ответ 7

Если вам просто нужно знать, какая позиция мыши соответствует данным, то d3 уже делает это для вас.

.on("click", function(d,i) {
    console.log("Clicked on " + d);
});

Я обновил Fiddle от @AmeliaBR http://fiddle.jshell.net/dMpbh/17/

Ответ 8

Вы можете легко получить индекс объекта/данные в обратном вызове

.on("click", function(d,i) {
    console.log("Clicked on index = " + i); 
    console.log("Clicked on data  = " + d); 
    // d == imageScale.domain()[1]
}); 

d - это значение самого инвертированного значения.
Вам не нужно использовать obj.domain() [index].