Начало шкалы времени оси d3 с нуля - PullRequest
0 голосов
/ 11 сентября 2018

Я создаю график, который использует шкалу времени. Мне бы хотелось, чтобы на оси X было показано время, начиная с нуля и начиная с интервала в 5 секунд каждый.

--------------------------------
:00  :05  :10  :15  :20  :25  :30

Мои данные имеют временные метки, которые приводятся к объектам даты. Шкалы основаны на этих временных метках.

(Примечание: я использую d3 v4 / 5).

D3 имеет изящную функцию для отображения временных интервалов, но эти интервалы начинаются со времени в объектах данных.

Я мог бы конвертировать свои данные, чтобы все время начиналось с нуля, но это могло бы создать дополнительные проблемы, поскольку я выстраиваю несколько наборов данных в одном и том же масштабе времени. Мне интересно, есть ли более элегантный способ использовать одну из функций форматирования тиков для отображения тиков, отличных от масштаба, или для вычисления на лету, чтобы начать с нуля секунд.

Заранее спасибо.

РЕДАКТИРОВАТЬ: Вот более полный фрагмент кода.

var videoData = [{
    "id": "1",
    "user_id": "_jlxvt8445494296",
    "video_id": "test",
    "time": "2018-09-11 15:39:20",
    "metric": "4"
  },
  {
    "id": "2",
    "user_id": "_jlxvt8445494296",
    "video_id": "test",
    "time": "2018-09-11 15:39:26",
    "metric": "2"
  },
  {
    "id": "3",
    "user_id": "_jlxvt8445494296",
    "video_id": "test",
    "time": "2018-09-11 15:39:27",
    "metric": "3"
  },
  {
    "id": "4",
    "user_id": "_jlxvt8445494296",
    "video_id": "test",
    "time": "2018-09-11 15:39:38",
    "metric": "1"
  }
];

var svg = d3.select("svg"),
  width = 400,
  height = 200;

var parseTime = d3.timeParse("%Y-%m-%d %H:%M:%S");

//coerce to d3 timeParse object
videoData.forEach(function(d) {
  d.time = parseTime(d.time);
});

var x = d3.scaleTime()
  .rangeRound([0, width])
  .domain(d3.extent(videoData, function(d) {
    return d.time;
  }));

var y = d3.scaleLinear()
  .rangeRound([height, 0])
  .domain(d3.extent(videoData, function(d) {
    return d.metric;
  }));


var line = d3.line()
  .x(function(d) {
    return x(d.time);
  })
  .y(function(d) {
    return y(d.metric);
  })
  .curve(d3.curveBasis);


svg.append("g")
 .attr("transform", "translate(10," + height + ")")
 .call(d3.axisBottom(x).tickFormat(d3.timeFormat(":%S")));

svg.append("path")
  .datum(videoData)
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("d", line);
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="420" height="220"></svg>

1 Ответ

0 голосов
/ 11 сентября 2018

Вы должны выполнить все расчеты относительно начала видео.

Рассчитать разницу во времени в ms относительно начала видео и преобразовать это время ms в дату new Date(ms).Вы получите ms-time для Date с помощью datevar.getTime().

. Чтобы преодолеть часовой пояс, вы должны выполнить полное отображение времени в UTC.

Под осью, отображающей времяс 00:00 до 01:40 - первые 100 секунд, каждые 5 секунд - галочка.

var parseTime = d3.timeParse("%Y-%m-%d %H:%M:%S");//2018-09-10 21:06:34

var formatSecond = d3.utcFormat(":%S"),
    formatMinute = d3.utcFormat("%M:%S");

function multiFormat(date) {
  return (d3.timeMinute(date) < date ? formatSecond : formatMinute)(date);
}

var width = 500;
var height = 100;
var g = d3.select("#chart").append("svg").attr("width", width + 40).attr("height", height + 40)
          .append("g").attr("transform", "translate(20,20)");

var x = d3.scaleUtc()
    .rangeRound([0, width])
    //.domain(d3.extent(data, function(d) { return d.time; }));
    .domain([new Date(0), new Date(100*1000)]);

g.append("g")
  .attr("transform", "translate(0," + height + ")")
  //.call(d3.axisBottom(x).ticks(d3.timeSecond.every(5)));
  .call(d3.axisBottom(x).ticks(d3.utcSecond.every(5)).tickFormat(multiFormat));
<script src='http://d3js.org/d3.v5.min.js' charset='utf-8'></script>
<div id="chart"></div>
...