我正在尝试找出将Rails后端需要的数据暴露到前端以绘制过去30天数据的最佳方法,无论是否每天记录一个条目过去30天与否。
我的控制器代码如下:
@symptoms = @current_member.symptoms
@symptoms_array ||= []
@symptoms.each do |symptom|
array = [ Time.parse(symptom.date).getutc.iso8601, symptom.level.to_i ]
@symptoms_array.push(array)
end
在我看来,我只是把这些数据放到一个元素的data
属性上用JS读取(我知道,有更好的方法可以做到这一点......)。
<div id="graph" class="graph" data-symptoms="<%= @symptoms_array %>">
然后我的Highcharts JS实例化看起来像这样:
const data = $('#graph').data('symptoms');
Highcharts.chart('graph', {
chart: {
type: 'column',
title: 'Pain levels'
},
xAxis: {
categories: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Pain level'
},
min: 0,
max: 10,
tickInterval: 1
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.y}'
},
series: [{
name: 'Pain level',
data: data
}]
});
我需要的是图表显示过去30天内每天的症状,无论当天是否有条目(它应该在没有条目的情况下显示0天)。并且X轴应该显示M ... F与星期几的相关性。现在,使用硬编码数组,它只显示M,T,W,T,F,S,S,7,8,9,10等。
答案 0 :(得分:1)
我建议您将groupdate
gem(https://github.com/ankane/groupdate)与chartkick
(https://github.com/ankane/chartkick)结合使用。
在您的情况下,您可以使用以下内容:
@symptoms = current_user.symptoms.group_by_day(:created_at).count
按天聚集所有症状。然后绘制它们,例如:
<%= column_chart @symptoms %>
查看gems文档以获取更多示例。
答案 1 :(得分:1)
要考虑两件事:数组需要包含所有日期,包括没有数据的日期,每个日期都需要采用适当的格式;所以我将做以下事情:
data_series
数组。label
代替categories
。创建一个哈希来存储值,其中每个键都是date
(Date
格式),其值为level
:
def action
@symptoms_hash = @current_member.symptoms.each do |symptom|
date = Time.parse(symptom.date).getutc.iso8601.to_date
symptoms_hash[date] = symptom.level.to_i
end
end
请注意添加的.to_date
,这样我们就可以更轻松地将日期转换为javascript格式。
def data_series(symptoms_hash)
dates = (symptoms_hash.keys.min..symptoms_hash.keys.max).to_a
dates.map do |date, value|
js_date = "Date.UTC(#{date.year}, #{date.month - 1}, #{date.day})"
"[#{js_date}, #{symptoms_hash[date].to_i}]"
end
end
要理解的一些注意事项:
dates
代表要绘制的时间范围,并从symptoms_hash
中的最小和最长日期获取其第一个和最后一个日期。Date.UTC
用于创建有效的 javascript 日期,因此 highcharts 可以将其识别为 date ,这将让我们获得匹配的星期几。 date.month - 1
被使用是因为javascript中的月份以0
开头,您需要将1
减去日期的月份,否则您的日期会错误。 使用刚刚创建的帮助器设置data
并将categories
替换为labels
,这需要自定义formatter
来显示名称中的第一个字母星期几的名字。
<script type="text/javascript">
const data = [<%= data_series(@symptoms_hash).join(",") %>];
Highcharts.chart('graph', {
chart: {
type: 'column',
title: 'Pain levels'
},
xAxis: {
type: 'datetime',
labels: {
formatter: function() {
var dayOfWeek = Highcharts.dateFormat('%A', this.value);
var firstLetter = dayOfWeek.substring(0, 1);
return firstLetter;
}
},
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Pain level'
},
min: 0,
max: 10,
tickInterval: 1
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.y}'
},
series: [{
name: 'Pain level',
data: data
}]
});
</script>
设置join
时请注意data
,它用于创建图表series
工作所需的数组数组。