C3js> Временные значения x не равномерно распределены
У меня проблема с метками, присвоенными значениям моего графика.
График - это таймсервис. Я добавляю значения, используя свойство "columns" c3js.
Я использую чистые временные метки (в секундах), а затем преобразовываю их в строки с помощью label.format.
Однако, это то, что происходит:
https://drive.google.com/file/d/0B9GDftIYQFIVb2Z3N2JfS2pzVjg/view?usp=sharing
поскольку вы можете заметить, что пространство распределено неравномерно, между 18-21, 25-28 октября и 1-4, 4-7 ноября всего два дня, а все остальные имеют три дня между датами.
Что вызывает это?
Я хотел бы иметь равномерные пробелы пробелов (столько же дней).
Вот код с кодом:
http://jsfiddle.net/ok1k6yjo/
var array_times = [1414540800, 1414627200];
var array_values = [67, 66.22];
var labelWeight = 'weight in kg';
var window_period = (30 * 24 * 3600); // last 30 days
var today = Math.floor(new Date(2014,10,20,0,0,0,0).getTime() / 1000);
var timeEnd = today;
var timeStart = today - window_period;
var toShowTime = [1414540800, 1414627200];
var toShowValues = [67, 66.22];
var minT = Math.min.apply(null, array_times),
maxT = Math.max.apply(null, array_times.concat(today));
var minV = Math.min.apply(null, array_values),
maxV = Math.max.apply(null, array_values);
function dateToString(e) {
var date = new Date(e * 1000);
return date.toDateString().substring(4);
}
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'times',
columns: [
['times'].concat(toShowTime),
[labelWeight].concat(toShowValues)],
labels: {
format: {
y: d3.format('.2')
}
},
type: 'scatter'
},
point: {
r: 6
},
legend: {
show: false
},
grid: {
x: {
show: true
},
y: {
show: true
}
},
axis: {
x: {
label: {
text: 'Time [days]'
},
type: 'timeseries',
tick: {
fit: false,
//count: 29,
rotate: -75,
multiline: false,
format: function (e, d) {
return dateToString(e);
}
},
height: 100
},
y: {
label: {
text: 'Weight [kg]',
position: 'outer',
min: minV - 10,
max: maxV + 10
},
tick: {
format: function (e, d) {
return parseFloat(e).toFixed(2);
}
},
}
}
});
chart.axis.range({min: {x:timeStart, y:minV-10}, max: {x:timeEnd, y:maxV+10}});
Небольшое различие связано с другой стартовой датой.
Вот еще одна скрипка с похожими проблемами.
http://jsfiddle.net/hfznh45w/5/
var d = (24 * 3600); // last 30 days
//var array_times = [1414540800-8*d, 1414540800-d, 1414540800, 1414627200, 1414627200 + d, 1414627200 + 2 * d, 1414627200 + 3 * d];
//var array_values = [61, 60, 67, 66.22, 68, 68, 68];
var array_times = [];
var array_values = [];
for (var i = -8; i < 30; i++) {
array_times.push(1414540800 + (i * d));
array_values.push(60 + i);
}
console.log(array_times);
console.log(array_values);
var labelWeight = 'weight in kg';
var window_period = (30 * 24 * 3600); // last 30 days
var today = Math.floor(new Date(2014, 10, 20, 0, 0, 0, 0).getTime() / 1000);
var timeEnd = today;
var timeStart = today - window_period;
var minT = Math.min.apply(null, array_times),
maxT = Math.max.apply(null, array_times.concat(today));
var minV = Math.min.apply(null, array_values),
maxV = Math.max.apply(null, array_values);
function dateToString(e) {
var date = new Date(e * 1000);
return date.toDateString().substring(4);
}
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'times',
columns: [
['times'].concat(array_times), [labelWeight].concat(array_values)],
labels: {
format: {
y: d3.format('.2')
}
},
type: 'scatter'
},
point: {
r: 6
},
legend: {
show: false
},
grid: {
x: {
show: true
},
y: {
show: true
}
},
axis: {
x: {
padding: {
left: 0,
right: 0,
},
label: {
text: 'Time [days]'
},
type: 'timeseries',
tick: {
fit: false,
rotate: -75,
multiline: false,
format: function (e, d) {
return dateToString(e);
}
},
height: 100
},
y: {
padding: {
top: 0,
bottom: 0
},
label: {
text: 'Weight [kg]',
position: 'outer',
min: minV - 10,
max: maxV + 10
},
tick: {
format: function (e, d) {
return parseFloat(e).toFixed(2);
}
}
}
}
});
chart.axis.range({
min: {
x: timeStart,
y: minV - 10
},
max: {
x: timeEnd,
y: maxV + 10
}
});
Любая подсказка/исправление более чем приветствуется.
Спасибо!
Ответы
Ответ 1
c3js позволяет указать, какие тики появятся на оси x.
Под ось /x/tick я добавил это -
values: [1413936000, 1414195200,1414454400,1414713600,1414972800,1415232000],
Я преобразовал ваши даты через три дня с помощью epoch converter.
Здесь ссылка для решения.
Я могу только предположить, если сетки не соответствуют этим трем дневным тикам, тогда они нажимали на новый день каждый n-й тик - отсюда и ваша проблема.
Кроме того, вы можете разместить сетки вручную.
Здесь код для оси x.
x: {
label: {
text: 'Time [days]'
},
type: 'timeseries',
tick: {
values: [1413936000, 1414195200,1414454400,1414713600,1414972800,1415232000],
fit: false,
//count: 29,
rotate: -75,
multiline: false,
format: function (e, d) {
return dateToString(e);
}
},
height: 100
},
Ответ 2
Установите значение tick.fit в false, чтобы метки были помещены в соответствии со значением x точек данных.
http://c3js.org/reference.html#axis-x-tick-fit
axis: {
x: {
tick: {
fit: true
}
}
}
Здесь образец с официального сайта http://c3js.org/samples/axes_x_tick_fit.html
Ответ 3
Я попробовал все предложенные ответы, но никто не дал мне то, что я хотел. Самый близкий ответ Partha, однако, выбрав category
, поскольку ваш тип диаграммы создает неприглядное дополнение слева и справа от графика.
Решение, которое наилучшим образом помогло мне, состояло в том, чтобы исключить метки из моего графика и вместо этого работать с графом indexed
. Оттуда я вручную отформатирую каждый индекс до нужной даты с помощью функции format
.
Здесь приведен упрощенный вариант исходного кода:
var d = (30 * 24 * 3600); // last 30 days
var array_times = [1414540800, 1414627200, 1414627200 + d, 1414627200 + 2 * d, 1414627200 + 3 * d, 1456528117];
var array_values = [67, 66.22, 68, 68, 68, 77];
var labelWeight = 'weight in kg';
var window_period = (30 * 24 * 3600); // last 30 days
function dateToString(e) {
var date = new Date(e * 1000);
return date.toDateString().substring(4);
}
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
// Notice that I removed the datetimes from here
[labelWeight].concat(array_values)
],
type: 'area'
},
point: {
r: 6
},
legend: {
show: false
},
grid: {
x: {
show: true
},
y: {
show: true
}
},
axis: {
x: {
label: {
text: 'Time [days]'
},
type: 'indexed',
tick: {
rotate: 90,
// I reference array_times manually here to
// convert the index to a user-friendly label
format: function (index) {
return dateToString(array_times[index]);
}
}
}
}
});
Рабочая скрипка: http://jsfiddle.net/uop61zLc/1/
Ответ 4
Я также столкнулся с проблемой. Вот как я решил. Используйте ось x как категорию, а не время, и манипулируйте соответствующим тиковым форматом, чтобы выглядеть так, как если бы он был временным.
Я упростил проблему, чтобы сделать ее общей.
Проблема (нерегулярный интервал):
var chart = c3.generate({
data: {
x: 'xtime',
xFormat: '%Y-%m-%d-%H-%M-%S',
columns: [
['xtime', '2015-05-20-05-10-13', '2015-05-20-05-11-13', '2015-05-21-06-10-13'],
['value', 30, 50, 20]
]
},
size: {
height: 300,
width: 600
},
axis: {
x: {
type: 'timeseries',
// type: 'category',
tick: {
// format: function(x) {
// var dateSubs = this.api.categories()[x].split('-'),
// newDate = new Date(dateSubs[0], dateSubs[1], dateSubs[2], dateSubs[3], dateSubs[4], dateSubs[5], 0);
//
// return newDate.toLocaleString();
// }
format: '%e-%b-%Y %H:%M'
}
}
}
});
<link href="#" onclick="location.href='https://rawgit.com/masayuki0812/c3/master/c3.css'; return false;" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<div id="chart"></div>