【问题标题】:D3 scale fails if first value is different than zero如果第一个值不为零,则 D3 缩放失败
【发布时间】:2013-11-14 21:48:23
【问题描述】:

在这个简单的例子中:http://jsfiddle.net/2VeGY/1/

<!doctype html>
<meta charset="utf-8">
<title>single column</title>
<style>
    *{margin:0,padding:0}
    input{width:800px;}
    nav{border:1px solid gray; width:850px;}
    li{display:inline-block; height:30px;  }
    li:hover{opacity:0.8}
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<body>

<input value="[{&quot;v&quot;:0,&quot;c&quot;:&quot;red&quot;},{&quot;v&quot;:100,&quot;c&quot;:&quot;#005&quot;},{&quot;v&quot;:200,&quot;c&quot;:&quot;#12d&quot;}, {&quot;v&quo\
t;:300,&quot;c&quot;:&quot;#1dd&quot;}, {&quot;v&quot;:400,&quot;c&quot;:&quot;red&quot;} ]">
  <nav>
    <ul>
    </ul>
  </nav>

  <script>

  var wscale = d3.scale.linear().range(["0px","800px"])

  update()
  d3.select("input").on("change",update)

  function update(){
      var data = JSON.parse(d3.select("input").property("value"));
      var li=d3.select("ul").selectAll("li").data(data);

      wscale.domain(d3.extent(data,function(d){return d.v}))

      li.enter().append("li")

      li
        .style("width",function(d,i){
            start=d.v
            i+1 == data.length ? end=d.v : end=data[i+1].v;
            return wscale(end-start)
        })
        .style("background-image",function(d,i){
            start=d.c;
            i+1 == data.length ? end=d.c : end=data[i+1].c;
            return "linear-gradient(to right, "+start+","+end+")"});

      li.exit().remove()

  }

  </script>

您可以更改步骤data[...].c 的色标及其位置data[...].v。 比例是动态更新的。

我的问题如下:如果第一个值不为零,为什么会搞砸?

非常感谢您的帮助!

【问题讨论】:

  • 我不确定你在问什么。什么第一价值?秤是怎么失效的?
  • 查看输入字段:jsfiddle.net/2VeGY/1 如果您将最后一个 v:400 值更改为,例如,v:1000,渐变会自动更新,但如果您更改 first v:0 值不同,宽度计算不正确

标签: css d3.js linear-gradients colorbar


【解决方案1】:

您看到这种行为是因为在您当前的代码中,您总是将 0 作为输入值传递给 wscale。对于最后一个li 元素,end 将与您的函数中的start 相同以设置width,因此您传递给wscale 的内容将为0。@ 的输入域987654330@被确定为输入值的范围,不考虑这个附加值。

您可以通过更改域的确定方式轻松解决此问题:

wscale.domain([0, d3.max(data,function(d){return d.v})]);

这假设您的所有v 值都是正数。

但是,您真正想要做的是考虑值之间的差异,因为这就是您传递给秤的内容。也就是说,差异的总和应该等于最大宽度。您可以按如下方式计算。

var sumdiff = 0;
for(var i = 0; i < data.length - 1; i++) {
    sumdiff += data[i+1].v - data[i].v;
}

那么尺度就变成了

wscale.domain([0, sumdiff]);

完整示例here

【讨论】:

  • 非常感谢您花时间向我解释这个错误。我不明白为什么它不适用于底片。我该如何解决?
  • 上面的代码假设 0 是刻度的开始(即最小值)。如果你有负值,你需要把最小的作为开始。基本上,您需要确保 0 在域中才能使其正常工作。
  • 对不起,这里jsfiddle.net/2VeGY/3 考虑到你的建议,结果还是有问题,特别是宽度的sum不再是600px了应该是因为范围是[0px,600px]
  • Anddd...jsfiddle.net/2VeGY/5 瞧,感谢您的建议,现在颜色条就像一个魅力!
【解决方案2】:

你不应该把引号放在范围内,应该是这样的:

.range([0,800])

【讨论】:

  • 你的建议暗示使用.attr("width"),它不起作用,或者使用.style("width")+"px"添加到值,它也不起作用
  • 同样的结果。它无法计算,比例,我认为代码中有一个我找不到的错误
  • 呃,我的错,我想我误解了你的问题,我以为你在问范围内的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
  • 2021-05-03
  • 2019-02-09
相关资源
最近更新 更多