D3.js 有序尺度反演

D3.js 有序尺度反演,d3.js,D3.js,有没有办法找到顺序标度的倒数 我在x轴上使用字符串值,这是使用顺序比例,我在鼠标移动时,我想找到x轴的反转,以找到鼠标位置上的字符串 有没有办法找到这个 var barLabels = dataset.map(function(datum) { return datum.image; }); console.log(barLabels); var imageScale = d3.scale.ordinal() .domain(barLabels) .ran

有没有办法找到顺序标度的倒数

我在x轴上使用字符串值,这是使用顺序比例,我在鼠标移动时,我想找到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);

我过去曾在需要时反转过域和范围

> 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)
    };
})
考虑将您的问题发布为功能请求,以备不时之需

  • 对这种功能有足够的需求
  • 我没有忽略任何东西,或者在本例中,文档下面隐藏了一些更有用的东西

  • 事实上,我认为没有针对有序比例的反转方法是没有意义的,但是可以使用ordinal.range()方法来解决这个问题,该方法将返回每个条的起始值,并使用ordinal.rangeBand()方法返回其宽度

    示例如下:

    有关守则如下:

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

    我理解为什么Mike Bostock可能不愿意在序数刻度上包含
    invert
    ,因为您无法返回单数真值。不过,这是我的版本。
    该函数获取一个位置并返回周围的基准。也许我以后会继续使用二进制搜索版本:-)


    我在被拒绝的pull请求中发现了一个更短的实现,它工作得非常好

    var ypos = domain[d3.bisect(range, xpos) - 1];
    
    其中域和范围是缩放域和范围:

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

    我通过构造具有相同域和范围的第二个线性标度,然后调用invert来解决这个问题

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

    如果您只想知道哪个鼠标位置对应于哪个数据,那么d3已经在为您做这些了

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

    我从@AmeliaBR更新了小提琴,最近我发现自己的处境与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());
    
    我拖动鼠标x位置(
    d3.mouse(this)[0]
    ),输入此
    inverseModeScale

    它从
    modeArray
    返回最接近鼠标x位置的元素。即使该值超出范围(-400或940),它也会返回正确的元素

    答案可能看起来有点特定于滑块,但无论如何都会发布,因为它是有效的(我认为),而且这个问题在谷歌上“d3反转顺序”的最热门结果中


    注意:此答案使用D3V4。

    您可以在回调中轻松获取对象的索引/数据

    .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]。

    我很乐意为该功能请求投票(对于
    ordinal.invert()
    方法)。与其他尺度上的反演方法一样,有时结果是无效的,但大多数情况下是有效的。不过,我们需要一些额外的参数来决定如何处理等同于填充空间的值。我们是否可以向Mike提出这一点,以便将来对d3.js v4进行增强?@NickBraunagel这是一个很好的建议,实际上是一个正式的建议!做这件事的地方应该是D3Github问题跟踪器:@AmeliaBR nice,就可以了。谢谢你的提示@AmeliaBR仅供参考-看起来Mike已经被问到这个问题了。这是他的回答:谢谢你的跟进,@NickBraunagel。很高兴看到有人提出建议&正在进行讨论,即使没有理想、干净的解决方案。
    .call( d3.drag()
        .on("start.interrupt", function() { modeSlider.interrupt(); })
        .on("start drag", function() { inverseModeScale(d3.mouse(this)[0]); })
    )
    
    .on("click", function(d,i) {
        console.log("Clicked on index = " + i); 
        console.log("Clicked on data  = " + d); 
        // d == imageScale.domain()[1]
    });