Domanda

In this simple example: 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>

you can change the color scale of the steps data[...].c and their position data[...].v. The scale is updated dynamically.

My problem is the following: Why it messes up if the first value is different than zero?

Thanks a lot for your help!

È stato utile?

Soluzione

You're seeing this behaviour because with your current code, you always pass 0 as an input value to wscale. For the last li element, end is going to be the same as start in your function to set the width and therefore what you're passing to wscale will be 0. The input domain of wscale is determined as the extent of the input values and doesn't take this additional value into account.

You can easily fix this by changing how the domain is determined:

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

This assumes that all of your v values are positive.

However, what you really want to do is take into account the differences between the values, as that's what you're passing to the scale. That is, the total sum of differences should be equal to the maximum width. You can compute this as follows.

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

Then the scale becomes

wscale.domain([0, sumdiff]);

Complete example here.

Altri suggerimenti

you shouldn't put the quotation marks in the range, it should be like so:

.range([0,800])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top