如何用垂直折线图填充区域?

时间:2019-04-19 13:44:42

标签: javascript d3.js axis area

我正在尝试使用D3.js制作垂直图表,并感觉到该区域在线条和y轴之间具有颜色,但它从未被填充。它只填充一部分。

以下是我要获取的正确图表的图像:

correct-filled-chart

以下是我现在使用的错误图表的图像:

wrong-filled-chart

使用标准图表填充区域很简单。可以使用y0参数并将其设置为零,以填满x轴和y的上限值之间的所有区域。

使用垂直图表填充区域对我而言并不是那么简单,因为我无法使用y0来解决问题。对我而言,唯一可行的方法是在输入数组的末尾添加行值,并在其他元素上添加此值(x,y)=>(0,min-depth)。因此,对于x值,我总是至少有一个元素为零。

var allArray = [{
    "parameter": 0.32,
    "depth": -0.02
  },
  {
    "parameter": 0.32,
    "depth": -0.04
  },
  {
    "parameter": 0.325,
    "depth": -0.06
  },
  {
    "parameter": 0.33,
    "depth": -0.08
  },
  {
    "parameter": 0.335,
    "depth": -0.1
  },
  {
    "parameter": 0.33,
    "depth": -0.12
  },
  {
    "parameter": 0.315,
    "depth": -0.14
  },
  {
    "parameter": 0.325,
    "depth": -0.16
  },
  {
    "parameter": 0.33,
    "depth": -0.18
  },
  {
    "parameter": 0.335,
    "depth": -0.2
  },
  {
    "parameter": 0.335,
    "depth": -0.22
  },
  {
    "parameter": 0.315,
    "depth": -0.24
  },
  {
    "parameter": 0.32,
    "depth": -0.26
  },
  {
    "parameter": 0.33,
    "depth": -0.28
  },
  {
    "parameter": 0.34,
    "depth": -0.3
  },
  {
    "parameter": 0.345,
    "depth": -0.32
  },
  {
    "parameter": 0.355,
    "depth": -0.34
  },
  {
    "parameter": 0.37,
    "depth": -0.36
  },
  {
    "parameter": 0.365,
    "depth": -0.38
  },
  {
    "parameter": 0.335,
    "depth": -0.4
  },
  {
    "parameter": 0.32,
    "depth": -0.42
  },
  {
    "parameter": 0.3,
    "depth": -0.44
  },
  {
    "parameter": 0.29,
    "depth": -0.46
  },
  {
    "parameter": 0.235,
    "depth": -0.48
  },
  {
    "parameter": 0.22,
    "depth": -0.5
  }
];

draw2("#svg4a", allArray);

function draw2(selector2, allArray) {

  var data = allArray;

  var startElement = { depth: 0, parameter: 0.3 };

  data.unshift(startElement);

  var margin = {
    top: 20,
    right: 20,
    bottom: 0,
    left: 35
  };
  var width = 150 - margin.left,
    height = 580 - margin.top;

  var svg = d3.select(selector2)
    .append("svg")
    .attr("class", "SVGcontent")
    .attr("width", width + margin.left)
    .attr("height", height + margin.top);

  // Pattern definition
  const defs = svg.append('defs')
    .append('pattern')
    .attr('id', 'whitecarbon2')
    .attr('patternUnits', 'userSpaceOnUse')
    .attr('width', 4)
    .attr('height', 4)
    .append('path')
    .attr('stroke', '#010101')
    .attr('stroke-width', 1)
    .attr("opacity", 0.5)
    .attr('d', 'M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2');

  data.forEach(function(d) {
    d.parameter = parseFloat(d.parameter);
  });
  var xScale = d3.scaleLinear()
    .domain([
      d3.max(data, function(d) {
        return d.parameter
      }) + 0.4, 0
    ])
    .range([0, width]);

  var yScale = d3.scaleLinear()
    .domain([
      0,
      d3.min(data, function(d) {
        return d.depth
      })
    ])
    .range([0, height - 20]);

  var line = d3.line()
    .x(function(d) {
      return xScale(d.parameter)
    })
    .y(function(d) {
      return yScale(d.depth)
    });

  var artboard = svg.append("g")
    .attr("transform", "translate(35," + margin.top + ")");

  var area = d3.area()
  .x1(function(d) {
      return xScale(d.parameter)
  })
  .x0(xScale(0))
  .y(function(d) {
      return yScale(d.depth)
  });

  // add the area
  artboard.append("path")
    .datum(data)
    .attr("class", "areaColore1")
    .attr("d", area)
    .attr("fill", "#fefefe");

  // add the pattern
  artboard.append("path")
    .datum(data)
    .attr("class", "area")
    .attr("d", area)
    .style('stroke', '#777777')
    .attr("fill", "url(#whitecarbon2)");

  artboard.append("path")
    .attr("d", line(data))
    .attr("stroke-width", "2")
    .attr("fill", "none");

  var xAxis = d3.axisTop(xScale);

  ticks = xScale.ticks(1);
  ticks.push(0);
  ticks.push(0.3);
  xAxis.tickValues(ticks);
  var yAxis = d3.axisLeft(yScale);

  artboard.append("g")
    .attr("class", "xAxis")
    .call(xAxis)
    .selectAll("text")
    .attr("y", -15)
    .attr("x", 0)
    .attr("dy", ".35em")
    .attr("transform", "rotate(none)")
    .style("text-anchor", "middle");

  artboard.append("g")
    .attr("transform", "translate(0,0)")
    .attr("class", "yAxis")
    .call(yAxis);
  // Adding title label to axis Y
  artboard.append("text")
    .attr("transform", "rotate(90)")
    .attr("y", 30)
    .attr("x", 6)
    // .attr("dy", "1em")
    .style('fill', '#777777')
    .style("text-anchor", "start")
    .text("Depth [m]");


  function make_x_gridlines() {
    return xAxis.ticks(1);
  }

  function make_y_gridlines() {
    return yAxis.ticks(11);
  }


  artboard.append("g")
    .attr("class", "grid gridX")
    .call(make_x_gridlines()
      .tickSize(-height + margin.top - 50)
      .tickFormat("")
    )

  artboard.append("g")
    .attr("class", "grid gridY2")
    .attr("transform", "translate(0,0)")
    .call(make_y_gridlines()
      .tickSize(-200)
      .tickFormat("")
    )
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="svg4a"></div>

预期:从垂直值线到y轴的所有区域都用彩色填充。

实际:仅填充连接线的第一个点和最后一个点值之间的区域。

下面是一个实时示例:Live chart

注意: 我还尝试添加此代码以使参数字段中的值始终为0,因此图表已正确填充。

我添加的代码就是这个:

  var startElement = { depth: 0, parameter: 0.3 };

  data.unshift(startElement);

,即使不设置.x0(即使设置正确),它也可以正常工作。 但是我的目标是找到一种配置,在该配置中,我不必在输入数组值中插入假值。我认为插入.x0应该足以使图表完整填充,就像y0如果图表处于水平模式,则可以从零填充到参数值。 有没有一种方法可以不插入假值?

1 个答案:

答案 0 :(得分:1)

如果要使用垂直面积图,则不应使用xy0y1。您应改用yx0x1

var area = d3.area()
    .x1(function(d) {
        return xScale(d.parameter)
    })
    .x0(xScale(0))
    .y(function(d) {
        return yScale(d.depth)
    });

这是您所做的更改的代码:

var allArray = [{
    "parameter": 0.32,
    "depth": 0
  }, {
    "parameter": 0.32,
    "depth": -0.02
  },
  {
    "parameter": 0.32,
    "depth": -0.04
  },
  {
    "parameter": 0.325,
    "depth": -0.06
  },
  {
    "parameter": 0.33,
    "depth": -0.08
  },
  {
    "parameter": 0.335,
    "depth": -0.1
  },
  {
    "parameter": 0.33,
    "depth": -0.12
  },
  {
    "parameter": 0.315,
    "depth": -0.14
  },
  {
    "parameter": 0.325,
    "depth": -0.16
  },
  {
    "parameter": 0.33,
    "depth": -0.18
  },
  {
    "parameter": 0.335,
    "depth": -0.2
  },
  {
    "parameter": 0.335,
    "depth": -0.22
  },
  {
    "parameter": 0.315,
    "depth": -0.24
  },
  {
    "parameter": 0.32,
    "depth": -0.26
  },
  {
    "parameter": 0.33,
    "depth": -0.28
  },
  {
    "parameter": 0.34,
    "depth": -0.3
  },
  {
    "parameter": 0.345,
    "depth": -0.32
  },
  {
    "parameter": 0.355,
    "depth": -0.34
  },
  {
    "parameter": 0.37,
    "depth": -0.36
  },
  {
    "parameter": 0.365,
    "depth": -0.38
  },
  {
    "parameter": 0.335,
    "depth": -0.4
  },
  {
    "parameter": 0.32,
    "depth": -0.42
  },
  {
    "parameter": 0.3,
    "depth": -0.44
  },
  {
    "parameter": 0.29,
    "depth": -0.46
  },
  {
    "parameter": 0.235,
    "depth": -0.48
  },
  {
    "parameter": 0.22,
    "depth": -0.5
  }
];

draw2("#svg4a", allArray);

function draw2(selector2, allArray) {

  var data = allArray;

  var margin = {
    top: 20,
    right: 20,
    bottom: 0,
    left: 35
  };
  var width = 150 - margin.left,
    height = 580 - margin.top;

  var svg = d3.select(selector2)
    .append("svg")
    .attr("class", "SVGcontent")
    .attr("width", width + margin.left)
    .attr("height", height + margin.top);

  // Pattern definition
  const defs = svg.append('defs')
    .append('pattern')
    .attr('id', 'whitecarbon2')
    .attr('patternUnits', 'userSpaceOnUse')
    .attr('width', 4)
    .attr('height', 4)
    .append('path')
    .attr('stroke', '#010101')
    .attr('stroke-width', 1)
    .attr("opacity", 0.5)
    .attr('d', 'M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2');

  data.forEach(function(d) {
    d.parameter = parseFloat(d.parameter);
  });
  var xScale = d3.scaleLinear()
    .domain([
      d3.max(data, function(d) {
        return d.parameter
      }) + 0.4, 0
    ])
    .range([0, width]);

  var yScale = d3.scaleLinear()
    .domain([
      0,
      d3.min(data, function(d) {
        return d.depth
      })
    ])
    .range([0, height - 20]);

  var line = d3.line()
    .x(function(d) {
      return xScale(d.parameter)
    })
    .y(function(d) {
      return yScale(d.depth)
    });

  var artboard = svg.append("g")
    .attr("transform", "translate(35," + margin.top + ")");

  var area = d3.area()
    .x1(function(d) {
      return xScale(d.parameter)
    })
    .x0(xScale(0))
    .y(function(d) {
      return yScale(d.depth)
    });

  // add the area
  artboard.append("path")
    .datum(data)
    .attr("class", "areaColore1")
    .attr("d", area)
    .attr("fill", "#fefefe");

  // add the pattern
  artboard.append("path")
    .datum(data)
    .attr("class", "area")
    .attr("d", area)
    .style('stroke', '#777777')
    .attr("fill", "url(#whitecarbon2)");

  artboard.append("path")
    .attr("d", line(data))
    .attr("stroke-width", "2")
    .attr("fill", "none");

  var xAxis = d3.axisTop(xScale);

  ticks = xScale.ticks(1);
  ticks.push(0);
  ticks.push(0.3);
  xAxis.tickValues(ticks);
  var yAxis = d3.axisLeft(yScale);

  artboard.append("g")
    .attr("class", "xAxis")
    .call(xAxis)
    .selectAll("text")
    .attr("y", -15)
    .attr("x", 0)
    .attr("dy", ".35em")
    .attr("transform", "rotate(none)")
    .style("text-anchor", "middle");

  artboard.append("g")
    .attr("transform", "translate(0,0)")
    .attr("class", "yAxis")
    .call(yAxis);
  // Adding title label to axis Y
  artboard.append("text")
    .attr("transform", "rotate(90)")
    .attr("y", 30)
    .attr("x", 6)
    // .attr("dy", "1em")
    .style('fill', '#777777')
    .style("text-anchor", "start")
    .text("Depth [m]");


  function make_x_gridlines() {
    return xAxis.ticks(1);
  }

  function make_y_gridlines() {
    return yAxis.ticks(11);
  }


  artboard.append("g")
    .attr("class", "grid gridX")
    .call(make_x_gridlines()
      .tickSize(-height + margin.top - 50)
      .tickFormat("")
    )

  artboard.append("g")
    .attr("class", "grid gridY2")
    .attr("transform", "translate(0,0)")
    .call(make_y_gridlines()
      .tickSize(-200)
      .tickFormat("")
    )
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="svg4a"></div>


PS:要使面积图与图像中的面积图一样,您需要第一个深度为0的数据点。