D3: форматирование лет с помощью метода .tickValues()

#javascript #arrays #d3.js

#javascript #массивы #d3.js

Вопрос:

Я пытаюсь написать функцию для метода .tickValues на моей оси X, чтобы первый год в моем массиве данных записывался как полный год (2000), а остальные годы записывались как: ’01, ’02, ’03.. и так далее

вот масштаб, ось и данные:

 var xScale = d3.time.scale()
.range([0, width])
.domain(d3.extent(dataset, function(d) { return d.year }));

var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");

var dataset = [
{ year: "2000", age1: 31, age2: 10, age3: 32, age4: 27 },
{ year: "2001", age1: 32, age2: 12, age3: 30, age4: 26 },
{ year: "2002", age1: 24, age2: 19, age3: 32, age4: 25 },
{ year: "2003", age1: 26, age2: 18, age3: 31, age4: 25 },
{ year: "2004", age1: 22, age2: 17, age3: 34, age4: 27 },
{ year: "2004", age1: 24, age2: 17, age3: 33, age4: 26 },
{ year: "2006", age1: 31, age2: 15, age3: 32, age4: 22 },
{ year: "2007", age1: 30, age2: 15, age3: 35, age4: 20 },
{ year: "2008", age1: 27, age2: 18, age3: 31, age4: 24 },
{ year: "2009", age1: 25, age2: 15, age3: 35, age4: 25 },
{ year: "2010", age1: 34, age2: 12, age3: 33, age4: 21 },
{ year: "2011", age1: 31, age2: 14, age3: 32, age4: 23 },
{ year: "2012", age1: 27, age2: 18, age3: 30, age4: 25 },
{ year: "2013", age1: 25, age2: 20, age3: 35, age4: 20 }
];

// convert years to dates
var parseDate = d3.time.format("%Y").parse;

dataset.forEach(function(d) {
    d.year = parseDate(d.year);
}); 
  

У меня есть функция для форматирования лет как ’01’, ’02 и т.д.:

  var formatYear = d3.time.format("'"  "%y");
  

Но когда я применяю к нему свою функцию в методе .tickValues(), это не работает:

 xAxis.tickValues( function(d){ if(d==dataset[0].year){return d;}else{return formatYear(d);} } );
  

Комментарии:

1. Похоже, вы пытаетесь установить домен вашего масштаба до того, как вы назначили массив данных своей переменной dataset . Переместить var dataset = … и т.д. В начало вашего блока кода здесь. Решает ли это проблему?

2. да, если я перемещу домен так, чтобы он находился после переменной dataset, то у меня все еще будет проблема

Ответ №1:

.tickValues() Метод используется для присвоения, какие значения получают отметки на оси, а не для присвоения, как они форматируются. Для этого вам следует использовать .tickFormat() метод.

Для начала, похоже, что вы делаете все в точности наоборот в опубликованном вами блоке кода. Вы должны определить свои данные и преобразовать свои значения в даты, прежде чем создавать домен вашей шкалы.

Поскольку вы превращаете значения года в своих данных в Date объекты, при создании вашей шкалы вы можете использовать унарный оператор, чтобы принудительно преобразовать их в количество мс…

 var xScale = d3.time.scale()
  .range([0, width])
  .domain(d3.extent(dataset, function(d) { return  d.year; }));
  

…который затем можно использовать в функции, которую вы передаете .tickFormat() :

 var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickFormat(function(d) {
  // if the year ends in 00 then display the full year
  if (d3.time.format('%Y')(d).slice(-2) === '00') {
    return d3.time.format('%Y')(d);
  } else {
    // otherwise shorten it to the final 2 digits
    return d3.time.format(''%y')(d);
  }
})
.ticks(d3.time.year, 1);
  

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

Вот демонстрационный JSFiddle