d3两个折线图之间的区域

时间:2016-03-11 22:57:09

标签: javascript d3.js

我想填写下面定义的两个区域图之间的线。我打了一个墙 - 我似乎有这样的问题,我创建的每条路径都没有其他值可供比较,我找到一个解决方案的努力似乎已经打了一个墙。

任何提示?

jQuery(document).ready(function ($) {

  var margin = {top: 20, right: 30, bottom: 40, left: 24},
  width = 430 - margin.left - margin.right,
  height = 225 - margin.top - margin.bottom,
  dotRadius = function() { return 3 };

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

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

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient('bottom')
    .tickFormat(d3.time.format('%b'));

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

  // This is a function that determines the colours of the lines drawn, up to 10.
  var color = d3.scale.category10();

  // This is used to format the time for our data.
  var formatTime = d3.time.format("%Y-%m-%d");

  var line = d3.svg.line()
    .x(function(d) { return x(d.Period); })
    .y(function(d) { return y(d.Value); })

  var areaBetweenGraphs = d3.svg.area()
  .x(function(d) { 
    console.log('ABG x is: ', d);
    return x(formatTime.parse(d.Time));
  })
  .y0(function(d) {
    console.log('ABG y0 is: ', d);
    return y(d.Quantity);
  })
  .y1(function(d) {
    console.log('ABG y1 is: ', d);
    return y(d.Amount);
  });

  var svg = d3.select("#pipeline-chart-render")
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

  // This separates the data into the lines we want, although the data is stored
  // In the same original object.
  color.domain(d3.keys(data[0].values[0]).filter(function(key) { 
    if (key === 'Amount'
     || key === 'Quantity') {
        return key
    }
  }));

  // This returns the data into two separate objects which can be graphed.
  // In this case, Amount and Quantity.
  var datasets = color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {
          Period: formatTime.parse(d.values[0].Time),
          Value: +d.values[0][name]};
      })
    };
  });

  console.log('datasets is: ', datasets);

  // set the minYDomainValue to zero instead of letting it be a lingering magic number.
  var minDomainValue = 0

  var minDate = d3.min(datasets, function(d0){
    return d3.min(d0.values, function(d1){
      return d1.Period;
    })
  }),
  maxDate = d3.max(datasets, function(d0){
    return d3.max(d0.values, function(d1){
      return d1.Period;
    })
  });

  x.domain([minDate, maxDate]);
  y.domain([
    minDomainValue,
    d3.max(datasets, function(c) { return d3.max(c.values, function(v) { return v.Value; }); })
  ])

  // Append the x-axis class and move axis around.
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)

  // Append the y-axis class.
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

  svg.append('g')

  var pipeline = svg.selectAll('.pipeline')
    .data(datasets);

  pipeline.enter()
    .append('g')
    .attr('class', 'pipeline');


  pipeline.append('path')
    .attr('class', 'line')
    .attr('id', function(d, i) {
      return 'pipeline-'+(i+1);
    })
    .attr('d', function(d) { console.log('line d is: ', d); return line(d.values); })
    .attr("data-legend",function(d) { return d.name})
    .style("stroke", function(d) { return color(d.name); })

  pipeline.exit().remove()

  // Rendering the points on the graph.
  var points = svg.selectAll('.pipelinePoint')
    .data(datasets);

  points
    .enter()
    .append('g')
    .attr('class', 'pipelinePoint');

  points.selectAll('.point')
    .data(function(d) {
      return d.values;
    })
    .enter()
    .append('circle')
    .attr('circleId', function(d, i) { 
      return 'circleId-'+i;
      })
    .attr('cx', function(d) {
      return x(d.Period);
      })
    .attr('cy', function(d) {
      return y(d.Value);
    })
    .attr('r', function(d) { 
      return dotRadius()
    });

});

var data = [
  {
    key: 1,
    values: [
      {
        Amount: 33,
        Quantity: 22,
        Time: '2015-01-01'
      }
    ]
  },
  {
    key: 2,
    values: [
      {
        Amount: 52,
        Quantity: 20,
        Time: '2015-02-01'
      }
    ]
  },
  {
    key: 3,
    values: [
      {
        Amount: 63,
        Quantity: 30,
        Time: '2015-03-01'
      }
    ]
  },
  {
    key: 4,
    values: [
      {
        Amount: 92,
        Quantity: 60,
        Time: '2015-04-01'
      }
    ]
  },
  {
    key: 5,
    values: [
      {
        Amount: 50,
        Quantity: 29,
        Time: '2015-05-01'
      }
    ]
  },
  {
    key: 6,
    values: [
      {
        Amount: 53,
        Quantity: 25,
        Time: '2015-06-01'
      }
    ]
  },
  {
    key: 7,
    values: [
      {
        Amount: 46,
        Quantity: 12,
        Time: '2015-07-01'
      }
    ]
  },
  {
    key: 8,
    values: [
      {
        Amount: 52,
        Quantity: 15,
        Time: '2015-08-01'
      }
    ]
  },
  {
    key: 9,
    values: [
      {
        Amount: 55,
        Quantity: 20,
        Time: '2015-09-01'
      }
    ]
  },
  {
    key: 10,
    values: [
      {
        Amount: 35,
        Quantity: 17,
        Time: '2015-10-01'
      }
    ]
  },
  {
    key: 11,
    values: [
      {
        Amount: 80,
        Quantity: 45,
        Time: '2015-11-01'
      }
    ]
  },
  {
    key: 12,
    values: [
      {
        Amount: 64,
        Quantity: 24,
        Time: '2015-12-01'
      }
    ]
  }
]

CSS如果你想让它变得不那么难看:

/* Line Chart CSS */

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

#pipeline-1,
#pipeline-2 {
  fill: none;
  stroke-width: 1.5px;
  stroke-linecap: round;

  transition: stroke-width 250ms linear;
  -moz-transition: stroke-width 250ms linear;
  -webkit-transition: stroke-width 250ms linear;

  transition-delay: 250ms
  -moz-transition-delay: 250ms;
  -webkit-transition-delay: 250ms;
}

.x.axis path {
/* Uncomment below if I want to remove x-axis line */
/*  display: none;*/
}

.line.hover path {
  stroke-width: 6px;
}

#pipeline-chart-render {
  padding-left: -50px;
}

.area {
  fill: steelblue;
}

1 个答案:

答案 0 :(得分:0)

这最终起作用了。

  // The following is for defining the area BETWEEN graphs.  
  var areaAboveQuantity = d3.svg.area()
    .x(line.x())
    .y0(line.y())
    .y1(0);

  var areaBelowQuantity = d3.svg.area()
    .x(line.x())
    .y0(line.y())
    .y1(height);

  var areaAboveAmount = d3.svg.area()
    .x(line.x())
    .y0(line.y())
    .y1(0);
  var areaBelowAmount = d3.svg.area()
    .x(line.x())
    .y0(line.y())
    .y1(height);

  var defs = svg.append('defs');

  defs.append('clipPath')
    .attr('id', 'clip-quantity')
    .append('path')
    .datum(datasets)
    .attr('d', function(d) {
       return areaAboveQuantity(d[1].values);
    });

  defs.append('clipPath')
    .attr('id', 'clip-amount')
    .append('path')
    .datum(datasets)
    .attr('d', function(d) {
      return areaAboveAmount(d[0].values);
    });


  svg.append('path')
    .datum(datasets)
    .attr('class', 'area')
    .attr('d', function(d) {
      return areaBelowQuantity(d[1].values)
    });

  // Quantity IS ABOVE Amount
  svg.append('path')
    .datum(datasets)
    .attr('d', function(d) {
      areaBelowQuantity(d[1].values);
    })
    .attr('clip-path', 'url(#clip-amount)')
    .style('fill', 'steelblue')
    .style('opacity', '0.2');


  // Amount IS ABOVE Quanity
  svg.append('path')
    .datum(datasets)
    .attr('d', function(d) {
      return areaBelowAmount(d[0].values);
    })
    .attr('clip-path', 'url(#clip-quantity)')
    .style('fill', 'steelblue')
    .style('opacity', '0.2');