Как изменить форму линии на закрытые бары в существующей диаграмме временных рядов, используя D3 - PullRequest
0 голосов
/ 04 апреля 2020

В настоящее время я отображаю временной ряд, используя d3, который отображается в виде линии enter image description here

. Теперь мне нужно, как мне показать закрытые бары, как показано ниже вместо линии, непрерывно движущейся как линия enter image description here

ниже мой рабочий код для временного ряда и js URL скрипта

http://jsfiddle.net/madpop143/5atLwk6h/latest/

var margin = {
    top: 20,
    left: 20,
    right: 20,
    bottom: 20
};

var width = 750 - margin.left - margin.right;
var height = 750 - margin.top - margin.bottom;

var randomDate = function (start, end) {
    return new Date(start.getTime() + Math.random()*(end.getTime() - start.getTime()));  
};

var data = d3.range(1000).map(function (d) {
    return {x: randomDate(new Date(2015, 0, 1), new Date(2015, 0, 20)), y: Math.random()*10};     
}).sort(function (a, b) {
    return a.x.getTime() - b.x.getTime();    
});

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

var g = svg.append('g')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

var x = d3.time.scale()
    .range([0, width]);
var xAxis = d3.svg.axis()
    .scale(x)
    .orient('bottom');

var y = d3.scale.linear()
    .range([height, 0]);
var yAxis = d3.svg.axis()
    .scale(y)
    .orient('left');

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

g.append('path')
    .attr('class', 'line')
    .attr('d', line(data));

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

g.append('g')
    .attr('class', 'y axis')
    .call(yAxis);

var tick = function () {
    var minMax = d3.extent(data, function (d) {
        return d.x; 
    });
    var duration = 250;
    // 1 day offset
    var offset = 24*60*60*1000;
    var from = minMax[0].getTime();
    // 2-days window
    var timeWindow = [from, from + 2*offset];

    // Recompute x,y domains
    x.domain(timeWindow);
    y.domain([0, d3.max(data, function (d) { return d.y; })]);

    // Redraw the line
    g.select('.line')
        .attr('d', line(data))
        .attr('transform', null);

    // Update x axis
    g.select('.x.axis')
        .transition()
        .duration(duration)
        .ease('linear')
        .call(xAxis);

    // Update y axis
    g.select('.y.axis')
        .transition()
        .duration(duration)
        .call(yAxis);

    //console.log(x(from))
    //console.log(x(from + offset));
    //console.log(x(from + 2*offset));

    // Slide the line to the left
    g.select('.line')
        .transition()
        .duration(duration)
        .ease('linear')
        .attr('transform', 'translate(' + x(from - duration) + ',0)')
        .each('end', function () { tick(); });

    // Remove first point
    data.shift();

}

tick();

1 Ответ

1 голос
/ 05 апреля 2020

Для решения, которое требует минимальных изменений в текущем коде, просто используйте interpolate("step-before") (или "step-after") и измените генератор линии на генератор области:

var line = d3.svg.area()
    .x(function (d) { return x(d.x); })
    .y1(function (d) { return y(d.y); })
    .y0(y(0))
    .interpolate("step-before");

Это остается путем, но это выглядит как прямоугольники без отступов между ними. Вот ваш код с этим изменением:

var margin = {
  top: 20,
  left: 20,
  right: 20,
  bottom: 20
};

var width = 750 - margin.left - margin.right;
var height = 750 - margin.top - margin.bottom;

var randomDate = function(start, end) {
  return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
};

var data = d3.range(1000).map(function(d) {
  return {
    x: randomDate(new Date(2015, 0, 1), new Date(2015, 0, 20)),
    y: Math.random() * 10
  };
}).sort(function(a, b) {
  return a.x.getTime() - b.x.getTime();
});

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

var g = svg.append('g')
  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

var x = d3.time.scale()
  .range([0, width]);
var xAxis = d3.svg.axis()
  .scale(x)
  .orient('bottom');

var y = d3.scale.linear()
  .range([height, 0]);
var yAxis = d3.svg.axis()
  .scale(y)
  .orient('left');

var line = d3.svg.area()
  .x(function(d) {
    return x(d.x);
  })
  .y1(function(d) {
    return y(d.y);
  })
  .y0(y(0))
  .interpolate("step-before");

g.append('path')
  .attr('class', 'line')
  .attr('d', line(data));

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

g.append('g')
  .attr('class', 'y axis')
  .call(yAxis);

var tick = function() {
  var minMax = d3.extent(data, function(d) {
    return d.x;
  });
  var duration = 250;
  // 1 day offset
  var offset = 24 * 60 * 60 * 1000;
  var from = minMax[0].getTime();
  // 2-days window
  var timeWindow = [from, from + 2 * offset];

  // Recompute x,y domains
  x.domain(timeWindow);
  y.domain([0, d3.max(data, function(d) {
    return d.y;
  })]);

  // Redraw the line
  g.select('.line')
    .attr('d', line(data))
    .attr('transform', null);

  // Update x axis
  g.select('.x.axis')
    .transition()
    .duration(duration)
    .ease('linear')
    .call(xAxis);

  // Update y axis
  g.select('.y.axis')
    .transition()
    .duration(duration)
    .call(yAxis);

  //console.log(x(from))
  //console.log(x(from + offset));
  //console.log(x(from + 2*offset));

  // Slide the line to the left
  g.select('.line')
    .transition()
    .duration(duration)
    .ease('linear')
    .attr('transform', 'translate(' + x(from - duration) + ',0)')
    .each('end', function() {
      tick();
    });

  // Remove first point
  data.shift();

}

tick();
svg {
  font: 10px sans-serif;
}

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

.line {
  fill: powderblue;
  stroke: steelblue;
  stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...