Flotr2 是 Flotr 的分支,它有独立版和插件版。独立版对旧版本做了不少改进,不但移除了对 Prototype 的依赖还改进移动设备的支持,比如支持 Touch 事件。数据系列也有了改进,构成系列的每个数组可以支持多个元素,旧版的只支持两个(对应 x 和 y)。插件版可灵活选择并自由扩展插件。详见 Flotr2 官网。
快速入门
官网提供的插件版实例适合演示 Flotr2 的全部功能特性,但不太适合入门学习。其实只要你有 Flotr 的基础,只要导入必需的 js 文件就行了。通常情况下,除了 imagediff.js
和 yepnope.js
,lib 和 js 根目录下的全部的 js 文件是不可少的,应该最先加载,然后导入相应图表类型和插件所需的 js 文件。比如要绘制直线或区域图,需要导入 lines.js
和 points.js
。如果要绘制标签、网格线和 ToolTip,需要导入 labels.js
、grid.js
和 hit.js
。其它的代码就和以前的一样了。具体请参看我用 Flotr2 插件版改写的实例:
$(function () {
drawCharts("1d");
$('button').click(function () {
drawCharts(this.name);
});
});
function drawCharts(rng) {
var toolTip_dateFormat;
if (rng.indexOf('d') != -1) {
toolTip_dateFormat = '%m/%d/%y %h:%M:%S';
} else {
toolTip_dateFormat = '%m/%d/%y';
}
var container = document.getElementById('container');
container.innerHTML = '<span class="info">Loading...</span>';
$.get('stock.aspx', { symbol: 'YHOO', range: rng },
function (data) {
/**
* Parse the text from the server.
*/
var arr = data.split('\n');
var dataProvider = [];
var i, len, tmp, ms, close, open, high, low;
len = arr.length;
for (i = 0; i < len; i++) {
tmp = arr[i].split(',');
ms = parseInt(tmp[0]);
close = parseFloat(tmp[1]);
open = tmp[2];
high = tmp[3];
low = tmp[4];
dataProvider[i] = [i, close, open, high, low, ms];
}
if (len > 1) {
var n, t;
var tu = Flotr.Date.timeUnits;
var span = dataProvider[i - 1][5] - dataProvider[0][5];
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'],
xaxis: {
mode: 'timeEx',
tickFormatter: function (n) {
var d = new Date(dataProvider[n][5]);
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', '#0066DD'],
fillOpacity: 0.9,
},
mouse: {
track: true,
trackAll: true,
relative: true,
position: 'ne',
lineColor: '#06D',
fillColor: '#fff',
fillOpacity: 0.9,
trackFormatter: function (obj) {
var item = obj.series.data[obj.index];
var d = new Date(item[5]);
var str = "";
str += "Date: " + Flotr.Date.format(d, toolTip_dateFormat) + "<br/>";
str += "Open: " + item[4] + "<br/>";
str += "<font color='#009045'>High: " + item[2] + "</font><br/>";
str += "<font color='#BF272D'>Low: " + item[3] + "</font><br/>";
str += "Close: " + item[1];
return str;
},
crosshair: { mode: 'xy' }
},
grid: {
outlineWidth: 1,
outlineColor: '#2B4657'
},
shadowSize: 0
}
var D = Flotr.DOM;
D.empty(container);
chart_container = D.node('<div id="chart_container"></div>');
D.insert(container, chart_container);
Flotr.draw(chart_container, [dataProvider], options);
} else {
container.innerHTML = '<span class="info">This chart is not available.</span>';
}
}
);
}
注意:stock.aspx 股票 Ajax 服务见使用 Flotr 绘制股票图
可以看到,上面的实例有用到 Jquery 而不是 Prototype。当然也可以都不用。另外个人觉得鼠标跟踪和十字线应该在 hit 事件触发时同时绘制,因此我将 Crosshair 功能整合到 hit.js
中了。还有对 xaxis
扩展了一种 mode:timeEx
,详见我前面写的文章。
限制鼠标跟踪
Flotr2 hit 插件很好用,但有一个缺点:鼠标跟踪有时会超出图表范围显示。如果图表是满屏显示,那这就是个 Bug 了。其实,很容易就能限制鼠标跟踪始终在图表范围中显示。原理是这样的:鼠标跟踪显示后,如果它的位置超出图表右端,需要重新定位到 west
方向;它的位置超出图表顶端,重新定位到 south
方向。依次类推。如下代码:
//east
if(D.size(mouseTrack).width + n.xaxis.d2p(n.x) + m >= this.plotWidth){
mouseTrack.style.left = 'auto';
mouseTrack.style.right = m - left - n.xaxis.d2p(n.x) + this.canvasWidth + 'px';
}
//north
if(n.yaxis.d2p(n.y) - D.size(mouseTrack).height - m <= 0){
mouseTrack.style.top = m + top + n.yaxis.d2p(n.y) + 'px';
mouseTrack.style.bottom = 'auto';
}
//west
if(n.xaxis.d2p(n.x) - D.size(mouseTrack).width - m <= 0){
mouseTrack.style.left = m + left + n.xaxis.d2p(n.x) + 'px';
mouseTrack.style.right = 'auto';
}
//south
if(n.yaxis.d2p(n.y) + D.size(mouseTrack).height + m >= this.plotHeight){
mouseTrack.style.top = 'auto';
mouseTrack.style.bottom = m - top - n.yaxis.d2p(n.y) + this.canvasHeight + 'px';
}
警告:上述代码一定要加在 D.show(mouseTrack);
之后,不然取不到鼠标跟踪的宽度和高度。
同步鼠标跟踪
同步 Flotr2 Chart 的鼠标跟踪比起同步 Flex Chart 的数据提示要麻烦,而且 Flotr 与 Flotr2 调用的 API 还不一样。Flotr 中的 flotr:hit
事件对象有一个 memo
属性,而 Flotr2 中的 flotr:hit
事件对象其实就是一个 nearest
对象。不仅如此,在 Flotr2 中调用 graph.hit(mouse);
会报错,得使用 graph.hit.drawMouseTrack(n);graph.hit.drawHit(n);
来实现,详见本实例中的 doHit 函数:
function doHit(graph, e, container) {
var n = Flotr.clone(e);
graph.hit.clearHit();
var offset = Flotr.DOM.position(container);
var xaxis = graph.axes.x;
var yaxis = graph.axes.y;
var s = graph.series[0];
var index = n.index;
var point = s.data[index];
n.xaxis = xaxis;
n.yaxis = yaxis;
n.x = point[0];
n.y = point[1];
graph.hit.drawMouseTrack(n);
graph.hit.drawHit(n);
}
参考示例
访问 codepen 查看完整项目代码及最终效果。
评论 (0)