根据偏差设置D3线行程

时间:2015-07-30 10:23:02

标签: javascript d3.js

以下是我的数据示例:

x   var min max
045 53.4    55  60
046 52.2    51  60
047 52.7    52  60
048 53.1    53  60
049 49.0    54  60
050 50.4    55  60
051 51.1    56  60
052 52.3    51  60
053 54.6    52  60
054 55.1    53  60
055 51.5    53  60
056 53.6    54  60
057 52.3    55  60

我想将var与x进行对比,但如果var在[min,max]内,则该线的颜色应为黑色,如果在外面则为红色。

如果确定但是我无法更改颜色,则绘制线条。我试过了:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  margin: auto;
  width: 960px;
}

text {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.x.axis path {
  display: none;
}

.line {
  fill: none;
  stroke: #000000;
  stroke-width: 1.5px;
}

</style>
<body>
<script src="lib/vendor/d3/d3.min.js"></script>
<script>

var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.x); })
    .y(function(d) { return y(d.var); })
    .style('stroke', function(d) { return (d.var>d.min && d.var<d.max) ? 0 : d3.rgb('#EE0000'); });

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.tsv("smidata.tsv", function(error, data) {
  if (error) throw error;

  x.domain([data[0].x, data[data.length - 1].x]);
  y.domain(d3.extent(data, function(d) { return d.var; }));

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Measurement");

  svg.append("path")
      .datum(data)
      .attr("class", "line")
      .attr("d", line);
});

</script>
</body>

但风格不是这里的功能。

谢谢!

修改

由于提供的链接,我想到了如何做到这一点。虽然还很粗糙。如果存在更简单的解决方案,欢迎使用。

<!DOCTYPE html>
<meta charset="utf-8">
<style>
   body {
      margin: auto;
      width: 960px;
   }

   text {
      font: 10px sans-serif;
   }
   svg {
      width: 100%;
      height: 20em;
   }
   g.axis line,
   g.axis path {
      shape-rendering: crispEdges;
      fill: none;
      stroke: black;
   }
   g.plot line {
      stroke-width: 2;
   }
</style>

<body>
   <script src="lib/vendor/d3/d3.min.js"></script>
   <script>
      function update(data) {
         lines = lines.data(data);

         xScale.domain([data[0].x, data[data.length - 1].x]);
         var inter = d3.extent(data, function(d) { return d.var; });
         yScale.domain([0,100]);

         lines.enter().append("line");
         lines.each(function (d, i) {
               var elem = data[i];
               //plotting value for current point      

               //find next point
               var nextElem;
               if (i+1 == data.length) {
                  // there is no next value,
                  // so repeat this point as the end of line
                  //(line will have zero length)
                  nextElem = elem;
               } else {
                  nextElem = data[i+1];
               }
               d3.select(this)
                  .attr( //set coordinates:
                     {
                        x1: xScale(elem.x),
                        y1: yScale(elem.var),
                        x2: xScale(nextElem.x),
                        y2: yScale(nextElem.var)
                     }
               )
               //Set styles for individual line segments
               .style("stroke", (elem.var > elem.min && elem.var < elem.max) ? "black" : "red");
         });
      }

       //*** INITIALIZATION ***//

      var svg = d3.select("body").append("svg");

      var margin = {
            top: 20,
            right: 20,
            bottom: 30,
            left: 50
         },
         width = 960 - margin.left - margin.right,
         height = 500 - margin.top - margin.bottom;

      var xScale = d3.scale.linear()
         .range([0, width]);

      var yScale = d3.scale.linear()
         .range([height, 0]);

      var xAxis = d3.svg.axis()
         .scale(xScale)
         .orient("bottom");

      var yAxis = d3.svg.axis()
         .scale(yScale)
         .orient("left");

      svg.append("g")
         .attr("class", "x axis")
         .attr("transform", "translate(0," + height + ")")
         .call(xAxis);

      svg.append("g")
         .attr("class", "y axis")
         .call(yAxis)
         .append("text")
         .attr("transform", "rotate(-90)")
         .attr("y", 6)
         .attr("dy", ".71em")
         .style("text-anchor", "end")
         .text("Measurement");

      var lines = svg.append("g").attr("class", "plot").selectAll("line");

      d3.tsv("smidata.tsv", function (error, data) {
         if (error) throw error;
         update(data);
      });
   </script>
</body>

1 个答案:

答案 0 :(得分:0)

对于样式,请在每个path元素中使用style函数。

编辑:

对不起我完全误解了你的问题。我认为您最好的选择是首先准备相应的数据,以便您可以正确使用API​​。例如,以下方法完成工作:

var data = [
    {x: 45, variance: 53.4, min: 55, max: 60},
    {x: 46, variance: 52.2, min: 51, max: 60},
    {x: 47, variance: 52.7, min: 52, max: 60},
    {x: 48, variance: 53.1, min: 53, max: 60},
    {x: 49, variance: 49.0, min: 54, max: 60},
    {x: 50, variance: 50.4, min: 55, max: 60},
    {x: 51, variance: 51.1, min: 56, max: 60},
    {x: 52, variance: 52.3, min: 51, max: 60},
    {x: 53, variance: 54.6, min: 52, max: 60},
    {x: 54, variance: 55.1, min: 53, max: 60},
    {x: 55, variance: 51.5, min: 53, max: 60},
    {x: 56, variance: 53.6, min: 54, max: 60},
    {x: 57, variance: 52.3, min: 55, max: 60}
];

var prepareData = function(data){
    var result = [];
    data.forEach(function(d, i) {
        var x1,y1,x2,y2;
        // 0-length line
        if (i == data.length - 1) {
            x1 = x2 = d.x;
            y1 = y2 = d.variance; 
        } else {
            x1 = d.x;
            x2 = data[i+1].x;
            y1 = d.variance;
            y2 = data[i+1].variance;
        }
        result.push({points: [{x: x1, y: y1}, {x: x2, y: y2}], variance: d.variance, min: d.min, max: d.max});
    });
    return result;
}

data = prepareData(data);

接下来,您必须使用秤,以便符合您的兴趣。从您的示例中,我推断出以下值很好:

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.x); })
    .y(function(d) { return y(d.y); });

xExtents = d3.extent(data.map(function(d) { return d.points.map(function(d) { return d.x; }); }))

var x = d3.scale.linear()
    .domain([d3.min(xExtents[0]), d3.max(xExtents[1])])
    .range([0, width]);

var y = d3.scale.linear()
    .domain([0, 100])
    .range([height, 0]);

最后,绘制所有行非常简单:

var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

var lines = svg.selectAll('.line')
    .data(data);

lines
    .enter()
    .append('g')
    .append('path')
    .attr('class', 'line')
    .attr('d', function (d) { return line(d.points); })
    .style('stroke', function(d) { return (d.variance > d.min && d.variance < d.max) ? "black" : "red"; });

我创建了一个简单的fiddle尝试重新创建这样的场景,我鼓励你在进一步的问题中做,这样我们就可以看到你到目前为止所尝试的内容并更好地理解你想要实现的目标。

相关问题