使用 Ajax 的 Flot 图上的线条不前进
Lines do not progress on Flot graph using Ajax
我想用从 Ajax 中提取的实时数据做一个折线图。 Y轴是小数点后一位的浮点数据。 X轴上是格式化的时间戳,最好是“%H:%M:%S.
以下非 Ajax 示例工作正常:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery.flot.js"></script>
<script src="js/jquery.flot.time.js"></script>
</head>
<body>
<div id="legendcontainer" style="width: 1000px;position:"></div>
<div id="placeholder" style="width:1000px;height:400px;"></div>
<div id="legend" style="width:600px;height:300px;"> </div>
<script type="text/javascript">
var DataSet1 = [ [1341354816000, 1.1], [ 1341358185000, 2.2] , [ 1341361620000, 3.3] ];
var DataSet2 =[[1341354816000, 5.1], [ 1341358185000, 6.2] , [ 1341361620000, 7.3] ]
var datasets =
{
"DataSet1" :{ label : "DataSet1", data: DataSet1 },
"DataSet2" :{ label: "DataSet2", data: DataSet2 }
};
var firstTime =true;
function plotByChoice(doAll)
{
data = [];
if (doAll != null)
{
$.each(datasets, function(key, val)
{
data.push(val);
});
}
else
{
$('#legend .legendCB').each(
function(){
if (this.checked)
{
data.push(datasets[this.id]);
}
else
{
data.push({label: this.id, data: []})
}
}
);
}
$.plot($("#placeholder"),data, { series:
{
lines:
{
show: true,
},
points:
{
show: true
}
},
xaxis: {mode: "time" },
yaxis: { tickDecimals: 1 },
yaxes: [ { min: 0 },
{
alignTicksWithAxis: "right",
position: "right",
min :-25,
max:50
} ]
});
}
plotByChoice(this);
</script>
</body>
</html>
接下来,使用 Ajax 的修改版本不起作用。请注意,标签是用户定义的,数据集的总数是可变的。每个数据集只有一个点。错误控制台中没有显示 JavaScript 错误,图表上没有显示任何内容,在 Firebug 中我可以看到数据被提取了一次(但只有一次,我期望的 setInterval 每隔3 秒)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery.flot.js"></script>
<script src="js/jquery.flot.time.js"></script>
</head>
<body>
<div id="legendcontainer" style="width: 1000px;position:"></div>
<div id="placeholder" style="width:1000px;height:400px;"></div>
<div id="legend" style="width:600px;height:300px;"> </div>
<script type="text/javascript">
var datasets = {};
var firstTime =true;
function plotByChoice(doAll)
{
$.ajax({
url: "graphlist.php",
method: 'GET',
dataType: 'text',
success: function (data) {
datasets = $.parseJSON(data);}
});
data = [];
if (doAll != null)
{
$.each(datasets, function(key, val)
{
data.push(val);
});
}
else
{
$('#legend .legendCB').each(
function(){
if (this.checked)
{
data.push(datasets[this.id]);
}
else
{
data.push({label: this.id, data: []})
}
}
);
}
$.plot($("#placeholder"),data, { series:
{
lines:
{
show: true,
},
points:
{
show: true
}
},
xaxis: {mode: "time" },
yaxis: { tickDecimals: 1 },
yaxes: [ { min: 0 },
{
alignTicksWithAxis: "right",
position: "right",
min :-25,
max:50
} ]
});
}
setInterval(plotByChoice(this), 3000);
</script>
</body>
</html>
收到的样本数据集:
[
{
"label": "s#2 ch#1 (ch un)", "data": [[1422263853,22.7]]
}
,
{
"label": "s#2 ch#2 (2_ch2)", "data": [[1422263853,21.9]]
}
,
{
"label": "s#2 ch#3 (N/A)", "data": [[1422263853,21.7]]
}
]
非常感谢您的帮助,我已经为此度过了令人沮丧的一天。
此致,
伯特兰
首先,您希望在 ajax
调用完成后执行的任何代码 必须 在成功处理程序中。记住 ajax 调用是 async
,所以:
...
success: function (data) {
datasets = $.parseJSON(data);
}
});
// This part executes before the AJAX call completes
data = [];
if (doAll != null)
....
你需要做这样的事情:
success: function(data) {
datasets = $.parseJSON(data);
drawPlot(datasets);
}
});
function drawPlot(datasets){
data = [];
if (doAll != null) {
...
Second,您不应将 setInterval
与 AJAX 调用混用。由于您不知道 async
调用何时完成,因此无法保证时间,您最终会同时发生多个 AJAX 调用。
// again this is called in the success handler
function drawPlot(datasets){
...
setTimeout(function(){
plotByChoice(true)
}, 3000); //<-- ajax success is done, now wait 3 seconds and call again
}
这里 an example 全部修复。
谢谢,您的解释很有帮助,但您的示例不起作用。我可以看到 Ajax 调用在 Firebug 中工作,但图表仅显示一组点,仅此而已。
我将数组变量数据设为全局后,它就开始工作了。点数开始累积,但是 X 轴下没有线条和时间显示。我研究了一下,将发送的 Linux UTC 时间戳乘以 1000,将微秒更改为 JavaScript 毫秒。
它仍然不能正常工作:
1) 点与点之间没有线;
2)传说不断重复;
3) 图表应该继续向左移动而不是聚在一起,例如每个系列一次应该只显示 10 个点,并且属于最早时间戳的点在每次 Ajax 调用迭代时删除。
我很确定这对其他人有用,所以这里是完整的修改后的列表,可以正常工作。任何额外的帮助将不胜感激。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script data-require="jquery@1.11.0" data-semver="1.11.0" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://www.flotcharts.org/flot/jquery.flot.js"></script>
<script src="http://www.flotcharts.org/flot/jquery.flot.time.js"></script>
</head>
<body>
<div id="legendcontainer" style="width: 1000px;position:"></div>
<div id="placeholder" style="width:1000px;height:400px;"></div>
<div id="legend" style="width:600px;height:300px;"></div>
<script type="text/javascript">
var datasets = {};
var firstTime = true;
var data = [];
function plotByChoice(doAll)
{
$.ajax({
url: "graphlist.php",
method: 'GET',
dataType: 'text',
success: function(data)
{
datasets = $.parseJSON(data);
drawPlot(datasets);
}
});
function drawPlot(datasets)
{
if (doAll != null)
{
$.each(datasets, function(key, val)
{
data.push(val);
});
}
else
{
$('#legend .legendCB').each(
function()
{
if (this.checked)
{
data.push(datasets[this.id]);
}
else
{
data.push({
label: this.id,
data: []
})
}
}
);
}
$.plot($("#placeholder"), data, {
series: {
lines: {
show: true
},
points: {
show: true
}
},
xaxis: {
mode: "time", minTickSize: [1, "second"], timeformat: "%H:%M:%S"
},
yaxis: {
tickDecimals: 1
},
yaxes: [{
min: 0
}, {
alignTicksWithAxis: "right",
position: "right",
min: -25,
max: 50
}]
});
}
setTimeout(function()
{
plotByChoice(true)
}, 3000);
}
plotByChoice(this);
</script>
</body>
</html>
现在收到的 JSON 数据如下所示:
[
{
"label": "s#2 ch#1 (ch un)", "data": [[1422349909000,22.8]]
}
,
{
"label": "s#2 ch#2 (2_ch2)", "data": [[1422349909000,22.1]]
}
,
{
"label": "s#2 ch#3 (N/A)", "data": [[1422349909000,22.1]]
}
]
再次致以最诚挚的问候和感谢!
伯特兰
已解决。
马克的回答是正确的。需要修改的是后端。
它不会在每个系列中返回一个点,而是在内存中一次保留最后 n 个点和 returns n 个点。
JSON 可以存储在会话变量中。要清除图形,请取消设置会话变量。
要为系列添加点,只需进行一些快速字符串解析即可:
(PHP 代码)
/* 在此之前连接一个完整的 $item 以防该系列尚不存在 */
$mycharray = explode("\n", $_SESSION['JSON_STRUCTURE']);
$_SESSION['JSON_STRUCTURE'] = "";
$found = 0;
$num = count($mycharray);
for ($loop = 0; $loop < $num; ++$loop)
{
$mycharray[$loop] .= "\n";
if(InStr($mycharray[$loop], $mylabel) == -1)
{
$_SESSION['JSON_STRUCTURE'] .= $mycharray[$loop];
}
else
{
$found = 1;
// str_replace ( mixed $search , mixed $replace , mixed $subject)
$new = str_replace( "]\n", ",[" . $date . "," . $mytemperature . "]]\n", $mycharray[$loop]);
$_SESSION['JSON_STRUCTURE'] .= $new;
}
}
if($found == 0)
{
$_SESSION['JSON_STRUCTURE'] .= $item;
}
echo $_SESSION['JSON_STRUCTURE'];
希望这对其他人有帮助。
谢谢马克!
我想用从 Ajax 中提取的实时数据做一个折线图。 Y轴是小数点后一位的浮点数据。 X轴上是格式化的时间戳,最好是“%H:%M:%S.
以下非 Ajax 示例工作正常:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery.flot.js"></script>
<script src="js/jquery.flot.time.js"></script>
</head>
<body>
<div id="legendcontainer" style="width: 1000px;position:"></div>
<div id="placeholder" style="width:1000px;height:400px;"></div>
<div id="legend" style="width:600px;height:300px;"> </div>
<script type="text/javascript">
var DataSet1 = [ [1341354816000, 1.1], [ 1341358185000, 2.2] , [ 1341361620000, 3.3] ];
var DataSet2 =[[1341354816000, 5.1], [ 1341358185000, 6.2] , [ 1341361620000, 7.3] ]
var datasets =
{
"DataSet1" :{ label : "DataSet1", data: DataSet1 },
"DataSet2" :{ label: "DataSet2", data: DataSet2 }
};
var firstTime =true;
function plotByChoice(doAll)
{
data = [];
if (doAll != null)
{
$.each(datasets, function(key, val)
{
data.push(val);
});
}
else
{
$('#legend .legendCB').each(
function(){
if (this.checked)
{
data.push(datasets[this.id]);
}
else
{
data.push({label: this.id, data: []})
}
}
);
}
$.plot($("#placeholder"),data, { series:
{
lines:
{
show: true,
},
points:
{
show: true
}
},
xaxis: {mode: "time" },
yaxis: { tickDecimals: 1 },
yaxes: [ { min: 0 },
{
alignTicksWithAxis: "right",
position: "right",
min :-25,
max:50
} ]
});
}
plotByChoice(this);
</script>
</body>
</html>
接下来,使用 Ajax 的修改版本不起作用。请注意,标签是用户定义的,数据集的总数是可变的。每个数据集只有一个点。错误控制台中没有显示 JavaScript 错误,图表上没有显示任何内容,在 Firebug 中我可以看到数据被提取了一次(但只有一次,我期望的 setInterval 每隔3 秒)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="js/jquery.js"></script>
<script src="js/jquery.flot.js"></script>
<script src="js/jquery.flot.time.js"></script>
</head>
<body>
<div id="legendcontainer" style="width: 1000px;position:"></div>
<div id="placeholder" style="width:1000px;height:400px;"></div>
<div id="legend" style="width:600px;height:300px;"> </div>
<script type="text/javascript">
var datasets = {};
var firstTime =true;
function plotByChoice(doAll)
{
$.ajax({
url: "graphlist.php",
method: 'GET',
dataType: 'text',
success: function (data) {
datasets = $.parseJSON(data);}
});
data = [];
if (doAll != null)
{
$.each(datasets, function(key, val)
{
data.push(val);
});
}
else
{
$('#legend .legendCB').each(
function(){
if (this.checked)
{
data.push(datasets[this.id]);
}
else
{
data.push({label: this.id, data: []})
}
}
);
}
$.plot($("#placeholder"),data, { series:
{
lines:
{
show: true,
},
points:
{
show: true
}
},
xaxis: {mode: "time" },
yaxis: { tickDecimals: 1 },
yaxes: [ { min: 0 },
{
alignTicksWithAxis: "right",
position: "right",
min :-25,
max:50
} ]
});
}
setInterval(plotByChoice(this), 3000);
</script>
</body>
</html>
收到的样本数据集:
[
{
"label": "s#2 ch#1 (ch un)", "data": [[1422263853,22.7]]
}
,
{
"label": "s#2 ch#2 (2_ch2)", "data": [[1422263853,21.9]]
}
,
{
"label": "s#2 ch#3 (N/A)", "data": [[1422263853,21.7]]
}
]
非常感谢您的帮助,我已经为此度过了令人沮丧的一天。
此致, 伯特兰
首先,您希望在 ajax
调用完成后执行的任何代码 必须 在成功处理程序中。记住 ajax 调用是 async
,所以:
...
success: function (data) {
datasets = $.parseJSON(data);
}
});
// This part executes before the AJAX call completes
data = [];
if (doAll != null)
....
你需要做这样的事情:
success: function(data) {
datasets = $.parseJSON(data);
drawPlot(datasets);
}
});
function drawPlot(datasets){
data = [];
if (doAll != null) {
...
Second,您不应将 setInterval
与 AJAX 调用混用。由于您不知道 async
调用何时完成,因此无法保证时间,您最终会同时发生多个 AJAX 调用。
// again this is called in the success handler
function drawPlot(datasets){
...
setTimeout(function(){
plotByChoice(true)
}, 3000); //<-- ajax success is done, now wait 3 seconds and call again
}
这里 an example 全部修复。
谢谢,您的解释很有帮助,但您的示例不起作用。我可以看到 Ajax 调用在 Firebug 中工作,但图表仅显示一组点,仅此而已。
我将数组变量数据设为全局后,它就开始工作了。点数开始累积,但是 X 轴下没有线条和时间显示。我研究了一下,将发送的 Linux UTC 时间戳乘以 1000,将微秒更改为 JavaScript 毫秒。
它仍然不能正常工作:
1) 点与点之间没有线; 2)传说不断重复; 3) 图表应该继续向左移动而不是聚在一起,例如每个系列一次应该只显示 10 个点,并且属于最早时间戳的点在每次 Ajax 调用迭代时删除。
我很确定这对其他人有用,所以这里是完整的修改后的列表,可以正常工作。任何额外的帮助将不胜感激。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script data-require="jquery@1.11.0" data-semver="1.11.0" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://www.flotcharts.org/flot/jquery.flot.js"></script>
<script src="http://www.flotcharts.org/flot/jquery.flot.time.js"></script>
</head>
<body>
<div id="legendcontainer" style="width: 1000px;position:"></div>
<div id="placeholder" style="width:1000px;height:400px;"></div>
<div id="legend" style="width:600px;height:300px;"></div>
<script type="text/javascript">
var datasets = {};
var firstTime = true;
var data = [];
function plotByChoice(doAll)
{
$.ajax({
url: "graphlist.php",
method: 'GET',
dataType: 'text',
success: function(data)
{
datasets = $.parseJSON(data);
drawPlot(datasets);
}
});
function drawPlot(datasets)
{
if (doAll != null)
{
$.each(datasets, function(key, val)
{
data.push(val);
});
}
else
{
$('#legend .legendCB').each(
function()
{
if (this.checked)
{
data.push(datasets[this.id]);
}
else
{
data.push({
label: this.id,
data: []
})
}
}
);
}
$.plot($("#placeholder"), data, {
series: {
lines: {
show: true
},
points: {
show: true
}
},
xaxis: {
mode: "time", minTickSize: [1, "second"], timeformat: "%H:%M:%S"
},
yaxis: {
tickDecimals: 1
},
yaxes: [{
min: 0
}, {
alignTicksWithAxis: "right",
position: "right",
min: -25,
max: 50
}]
});
}
setTimeout(function()
{
plotByChoice(true)
}, 3000);
}
plotByChoice(this);
</script>
</body>
</html>
现在收到的 JSON 数据如下所示:
[
{
"label": "s#2 ch#1 (ch un)", "data": [[1422349909000,22.8]]
}
,
{
"label": "s#2 ch#2 (2_ch2)", "data": [[1422349909000,22.1]]
}
,
{
"label": "s#2 ch#3 (N/A)", "data": [[1422349909000,22.1]]
}
]
再次致以最诚挚的问候和感谢! 伯特兰
已解决。
马克的回答是正确的。需要修改的是后端。
它不会在每个系列中返回一个点,而是在内存中一次保留最后 n 个点和 returns n 个点。
JSON 可以存储在会话变量中。要清除图形,请取消设置会话变量。
要为系列添加点,只需进行一些快速字符串解析即可:
(PHP 代码) /* 在此之前连接一个完整的 $item 以防该系列尚不存在 */
$mycharray = explode("\n", $_SESSION['JSON_STRUCTURE']);
$_SESSION['JSON_STRUCTURE'] = "";
$found = 0;
$num = count($mycharray);
for ($loop = 0; $loop < $num; ++$loop)
{
$mycharray[$loop] .= "\n";
if(InStr($mycharray[$loop], $mylabel) == -1)
{
$_SESSION['JSON_STRUCTURE'] .= $mycharray[$loop];
}
else
{
$found = 1;
// str_replace ( mixed $search , mixed $replace , mixed $subject)
$new = str_replace( "]\n", ",[" . $date . "," . $mytemperature . "]]\n", $mycharray[$loop]);
$_SESSION['JSON_STRUCTURE'] .= $new;
}
}
if($found == 0)
{
$_SESSION['JSON_STRUCTURE'] .= $item;
}
echo $_SESSION['JSON_STRUCTURE'];
希望这对其他人有帮助。
谢谢马克!