我正在创建一个与StackOverflow信誉图非常相似的flot图。有一个小图表显示数据的鸟瞰级别,允许您选择一个范围并在较大的图形上显示,缩放。当任何一个图形悬停时,图例文本会更新以反映该x位置的值。
我遇到两个问题,在我的控制台等中绝对没有错误......
1:当我在“缩放器”图表上选择一个范围时,较大的“细节”图表会正确放大,但是当x值悬停时导致图例文本更新的代码将停止工作。点项鼠标悬停(导致工具提示)仍然有效,两位代码处于同一事件中。怪异。
2:一旦我放大,日期格式就会被抛出。尽管指定了timeformat
,日期仍会恢复为时间戳(并且它实际上适用于第一个绘图,在进行缩放之前)。
我录制了一个简短的截屏视频,以显示正在运行的问题:
我已经设置了一个显示日期/时间格式问题的JSFiddle 。出于某种原因,在该环境中,没有一个悬停事件按预期工作。
我错过了会导致这两个问题的事情吗?
//doPlot is originally called where ranges=null. This plots the entire universe
//of data on both charts. Once a range is selected, this is called again with
//ranges
var plot=null;
var plot2=null;
var updateLegendTimeout = null;
var latestPosition = null;
var datasets=null;
var currRange=null;
function doPlot(ranges){
currRange=ranges;
clearTimeout(updateLegendTimeout);
updateLegendTimeout = null;
var options = { //Options for large graph
lines: { show: true },
points: { show: true },
grid: { hoverable: true, clickable: false, autoHighlight: false, backgroundColor: { colors: ["#fff", "#eee"] }, markings: weekendAreas },
xaxis: {mode: 'time', timeformat: "%m/%d", minTickSize: [1, "day"]},
crosshair: { mode: "x" },
legend: {
show: true,
container: $('#legend'),
noColumns: 2
}
};
var options2 = { //options for small zoomer graph
lines: { show: true },
points: { show: false },
grid: { hoverable: true, clickable: true, autoHighlight: false, backgroundColor: { colors: ["#fff", "#eee"] }, markings: weekendAreas },
xaxis: {mode: 'time', timeformat: "%m/%d", minTickSize: [1, "month"]},
crosshair: { mode: "x" },
selection: { mode: "x" },
legend: { show: false }
};
if (currRange){ //if there is a range specified, extend options to include it.
options = $.extend(options, {
xaxis: {
min: currRange.xaxis.from,
max: currRange.xaxis.to
}
});
}
//Plot Large Graph with (or without) given range
plot = $.plot($("#placeholder"), datasets,options);
//plot the zoomer graph, only if it is null (it is set to null before ajax request for new chart)
if (!plot2) {
plot2 = $.plot($("#zoomer"), datasets, options2);
$("#zoomer").unbind("plotselected").bind("plotselected", function (event, ranges) {
//unbind/re-bind plotselected event to zoom in when a range is selected
doPlot(ranges);
}).unbind("plothover").bind("plothover", function (event, pos, item) {
//unbind/re-bind plothover event to to show tooltips and to change legend values
latestPosition = pos;
if (!updateLegendTimeout)
updateLegendTimeout = setTimeout(function(){
updateLegend(plot2);
}, 50);
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
var text = item.series.label.split(' = ');
showTooltip(item.pageX, item.pageY,
text[0] + ' ('+y+')');
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
});
}
doBinds();
}
function doBinds(){
$("#placeholder").unbind("plothover").bind("plothover", function (event, pos, item) {
latestPosition = pos;
if (!updateLegendTimeout)
updateLegendTimeout = setTimeout(function(){
updateLegend(plot);
}, 50);
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
var text = item.series.label.split(' = ');
showTooltip(item.pageX, item.pageY,
text[0] + ' ('+y+')');
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
});
}
答案 0 :(得分:3)
如果选择了一个范围,则x轴上的刻度问题与doPlot函数中的绘图选项的扩展方式有关。您需要使用`true作为第一个参数调用jQuery.extend,以便它执行深层复制。否则,当您使用x轴min和max扩展选项对象时,它会将模式设置为time来覆盖x轴对象。用这个替换那个位,它将解决这个问题。
if (currRange){ //if there is a range specified, extend options to include it.
options = $.extend(true, options, {
xaxis: {
min: currRange.xaxis.from,
max: currRange.xaxis.to
}
});
}
编辑:
因此,出现第一个问题是因为图例重绘时删除了图例项并添加了新项。您可以在文档就绪时存储对原始图例标签的引用,但是当图表重绘时,这些不再附加到DOM。您正在更新这些分离元素上的标签,而不是更新新创建的图例标签。尝试更新图例时尝试重新初始化图例集合:
//THIS IS MOST LIKELY WHERE THE PROBLEM IS OCCURRING!!!!
function updateLegend(thePlot) {
legends = $('.legendLabel');
clearTimeout(updateLegendTimeout);
updateLegendTimeout = null;
var pos = latestPosition;
var axes = thePlot.getAxes();
if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
pos.y < axes.yaxis.min || pos.y > axes.yaxis.max)
return;
var i, j, dataset = thePlot.getData();
for (i = 0; i < dataset.length; ++i) {
var series = dataset[i];
// find the nearest points, x-wise
for (j = 0; j < series.data.length; ++j)
if (series.data[j][0] > pos.x)
break;
// now interpolate
var y, p1 = series.data[j - 1], p2 = series.data[j];
if (p1 == null)
y = p2[1];
else if (p2 == null)
y = p1[1];
else
y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);
legends.eq(i).text(series.label.replace(/=.*/, "= " + y.toFixed(2)));
}
}