Flotr 的轴默认为线性轴 mode='normal'
。为什么要使用 Flotr 自定义线性轴来显示时间呢?正如上一篇文章所言:如果使用时间轴,当时间范围为五天时,会在当天与下一天之间绘制一大段多余的 连接线,而且轴标签有时会找不到对应的数据点而缺少实际意义。因此,有必要自定义线性轴而不是使用时间轴。
具体实现
这里的所有日期标签是用 axis.ticks
数组来管理的,同样在一种日期格式下,当前标签与下一日期标签和上一标签的文本不相同时才显示出来。请参考下面代码:
...
else if (o.mode == 'timeEx') {
// store all possible ticks.
var preLabel;
var nextLabel;
var r = axis.max - axis.min;
for(i = 0; i < r; ++i){
preLabel = o.tickFormatter(i);
nextLabel = o.tickFormatter(i + 1);
if(nextLabel != preLabel)
axis.ticks.push({ v: i + 1, label: nextLabel });
}
}
当两个日期标签间隔太近容易重叠时,我们也用了类似方法来移除,只不过在 Flex 中参照间距是相对的,而此处是绝对的。如下面代码:
function filterTicks(graph, axis){
if(axis.options.mode == 'timeEx'){
var w = axis.maxLabel.width;
//filter the labels
var len = axis.ticks.length;
if(len > 3){
var preTick;
var nextTick;
for (i = len - 1; i > 0; i--) {
preTick = axis.ticks[i - 1];
nextTick = axis.ticks[i];
//remove the middle label
if(nextTick){
if(axis.d2p(nextTick.v) - axis.d2p(preTick.v) < 9 * nextTick.label.length)
axis.ticks.splice(i - 1, 1);
}
//remove the last label
if(i == len - 1){
if(graph.plotWidth - axis.d2p(nextTick.v) < 3 * nextTick.label.length){
axis.ticks.pop();
}
}
//remove the first label
if(i == 1){
if(axis.d2p(preTick.v) < w / 3 ){
axis.ticks.shift();
}
}
}
}
len = axis.ticks.length;
xBoxWidth = graph.plotWidth / len;
}
}
使用方法很简单,将 xaxis
的 mode
指定为自定义的线性轴就行了。
参考代码
完整代码如下:
Html 代码
<div align="center" style="width:800px; padding:50px;">
<div id="chart_container"></div>
<div id="btn_container">
<button value="1 D" name="1d">1 D</button>
<button value="5 D" name="5d">5 D</button>
<button value="3 M" name="3m">3 M</button>
<button value="6 M" name="6m">6 M</button>
<button value="1 Y" name="1y">1 Y</button>
<button value="3 Y" name="3y">3 Y</button>
<button value="5 Y" name="5y">5 Y</button>
<button value="10Y" name="10y">10Y</button>
<button value="All" name="my">All</button>
</div>
</div>
JavaScript 代码
document.observe('dom:loaded', function () {
drawCharts("1d", false);
});
$('btn_container').childElements().each(function (btn) {
btn.observe('click', function () {
drawCharts(btn.name, true);
});
});
function drawCharts(range, initialized) {
$('chart_container').update('<span class="info">Loading...</span>');
var toolTip_dateFormat;
if (range.include('d')) {
toolTip_dateFormat = '%m/%d/%y %h:%M:%S';
} else {
toolTip_dateFormat = '%m/%d/%y';
}
new Ajax.Request('stock.aspx?symbol=YHOO&range=' + range, {
method: 'get',
onSuccess: function (transport) {
/**
* Parse the text from the server.
*/
var str = transport.responseText;
var arr = str.split('\n');
var len = arr.length;
if (len > 1) {
var closeData = [], hitData = [], ms;
for (var i = 0; i < len; i++) {
var tmp = arr[i].split(',');
ms = parseInt(tmp[0]);
closeData[i] = [i, parseFloat(tmp[1])];
hitData[i] = [ms, tmp[2], tmp[3], tmp[4], tmp[1]];
}
//get tick date format
var n, t, tu = Flotr.Date.timeUnits;
var span = hitData[len - 1][0] - hitData[0][0];
for (var pair in tu) {
n = Math.floor(span / tu[pair]);
// less than 3 times
if (0 < n && n < 72) {
t = Flotr.Date.timeUnits[pair];
}
}
var tick_dateFormat = Flotr.Date.getFormat(t, span);
var options = {
colors: ['#06D'],
title: "Yahoo Inc.",
xaxis: {
mode: 'timeEx',
tickFormatter: function (n) {
var d = new Date(hitData[n][0]);
var str = Flotr.Date.format(d, tick_dateFormat);
if (str == '0:00') {
return Flotr.Date.format(d, '%d');
}
if (str == 'Jan') {
return Flotr.Date.format(d, '%y');
}
return str;
},
background: '#CCD6DB'
},
yaxis: { tickDecimals: 2 },
lines: {
lineWidth: 1,
fill: true,
fillColor: '#CDE2F8',
fillOpacity: 0.9,
lineColor: null
},
mouse: {
track: true,
trackAll: true,
relative: true,
position: 'ne',
lineColor: '#06D',
fillColor: '#fff',
fillOpacity: 0.75,
trackFormatter: function (obj) {
var x = Math.floor(obj.x);
var item = hitData[x];
var str = "";
str += "Date: " + Flotr.Date.format(new Date(item[0]), toolTip_dateFormat) + "<br/>";
str += "Open: " + item[3] + "<br/>";
str += "<font color='#009045'>High: " + item[1] + "</font><br/>";
str += "<font color='#BF272D'>Low: " + item[2] + "</font><br/>";
str += "Close: " + closeData[x][1];
return str;
}
},
grid: { outlineWidth: 1 },
shadowSize: 0
}
$('chart_container').update();
Flotr.draw($('chart_container'), [closeData], options);
} else {
$('chart_container').update('<span class="info">This chart is not available.</span>');
}
}
})
}
后端服务代码
stock.aspx
股票 Ajax 服务见使用 Flotr 绘制股票图
评论 (0)