Как заполнить область вертикальной линейной диаграммой? - PullRequest
2 голосов
/ 19 апреля 2019

Я пытаюсь создать вертикальный график с D3.js и почувствовать область с цветом между линией и осью y, но она никогда не заполняется вообще.Это только заполнить часть.

Вот изображение правильного графика, который я пытаюсь получить:

correct-filled-chart

Вот изображениенеправильного графика у меня сейчас:

неправильно заполненный график

Со стандартным графиком заполнить область просто.Можно использовать параметр y0 и установить его в ноль, чтобы заполнить всю область между осью x и верхними значениями y в строке.

С вертикальной областью заливки мне не так просто, потому что я могуне используйте y0 для решения проблемы.Единственный способ заставить его работать - добавить в конец входного массива значения строк, другой элемент с этими значениями (x, y) => (0, min-глубина).Поэтому у меня всегда есть хотя бы один элемент с нулем для значений 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.

Факт: заполненная область только для соединительной линии междузначения первой и последней точек линии.

Вот живой пример: Живой график

NB: Я также пытался добавить этокод, чтобы в поле параметра всегда было 0, поэтому диаграмма была заполнена правильно.

Я добавил следующий код:

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

  data.unshift(startElement);

, и этот код работает также без установки .x0(даже если это правильно установить).Но моя цель состояла в том, чтобы найти конфигурацию, в которой я не обязан быть обязательным для вставки поддельного значения в значения входного массива.Я думаю, что вставки .x0 должно быть достаточно, чтобы заполнить график целиком, как y0 сделать заполнение от нуля до значений параметров, если график находится в горизонтальном режиме.Есть способ сделать это без вставки поддельного значения?

1 Ответ

1 голос
/ 19 апреля 2019

Если вы хотите вертикальную диаграмму площади, вы не должны использовать x, y0 и y1. Вы должны использовать y, x0 и x1 вместо:

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.

...