データロガーからのデータの時系列プロットを表示するために、AngularJS アプリケーションで Dygraphs を使用しています。Angular は新しいデータの取得と、データが到着したときにグラフ シリーズの更新を処理し、Dygraphs は Angular を使用してプロットを適切に更新します$watch()
。問題は、別のデータ セット、特にシリーズ数が少ないデータ セットに切り替えたい場合に発生します。コンソール エラーが表示されます (OS X 10.6.8 で Safari 5.1.9 を使用):
'undefined' is not an object (evaluating 'this.series_[b].yAxis')
の 2 行目dygraph-combined.js
。不都合なことは何も起こらないようで、グラフは正しく更新されますが、私はそれが起こらないことを望みます!
Angular でグラフ データ ソースを正しく切り替えるのにいくつか問題がありました。私にとってうまくいっ$timeout(,0)
たのは、他のオプションをすぐに変更しながら、呼び出し内でデータ ソースを変更することでした。これは、シリーズの数と、シリーズのタイトルおよび/または軸の数との間に (短い) 不一致があることを意味します。シリーズの数が変わらない、または増えない場合、このエラーは発生しません。誰が何がうまくいかないのかを見て、それを回避する方法を教えてもらえますか?
Dygraph をインスタンス化するための Angular ディレクティブを作成しました。
'use strict';
angular.module('dygraphs', []);
angular.module('dygraphs').directive('mrhDygraph', function ($parse, $q) {
return {
restrict: 'A',
replace: true,
scope: {data: '=', initialOptions: '@', options: '='},
link: function (scope, element, attrs) {
var dataArrived = $q.defer();
dataArrived.promise.then(function (graphData) {
scope.graph = new Dygraph(element[0], graphData, $parse(scope.initialOptions)(scope.$parent));
return graphData.length - 1;
}).then(function(lastPoint) {
scope.graph.setSelection(lastPoint);
scope.$emit('dygraphCreated', element[0].id, scope.graph);
});
var removeInitialDataWatch = scope.$watch('data', function (newValue, oldValue, scope) {
if ((newValue !== oldValue) && (newValue.length > 0)) {
dataArrived.resolve(newValue);
removeInitialDataWatch();
scope.$watch('data', function (newValue, oldValue, scope) {
if ((newValue !== oldValue) && (newValue.length > 0)) {
var selection = scope.graph.getSelection();
scope.graph.updateOptions({'file': newValue});
if ((selection >= 0) && (selection < newValue.length)) {
scope.graph.setSelection(selection);
}
}
}, true);
scope.$watch('options', function (newValue, oldValue, scope) {
if (newValue !== undefined) {
scope.graph.updateOptions(newValue);
}
}, true);
}
}, true);
}
};
});
次に、コントローラーで、次のようにグラフ データ ソースを切り替えます。
$scope.setGraphDataSource = function (plotData, sourceData, scaleFactor) {
$timeout(function () {
$scope[plotData] = [];
for (series in removeWatch) {
removeWatch[series]();
}
removeWatch = [];
var col = 0;
for (series in sourceData) {
removeWatch[series] = function (col) {
return $scope.$watch(function () {return $scope.logs[sourceData[col]].data.length},
function (newValue, oldValue, scope) {
updateCol(plotData, col, scope, scope.logs[sourceData[col]],
sourceData.length + 1, scaleFactor[col]);
})}(col);
col = col + 1;
}
}, 0);
}
$scope.showTemperatureGraph = function () {
$scope.setGraphDataSource('graphData', ['OutsideTemperature', 'InsideTemperature'], [1, 1]);
$scope.graphOptions = {labels: ['Time', 'Outside', 'Inside'],
series: {'Inside': {axis: 'y'}, 'Outside': {axis: 'y'}},
axes: {x: {valueFormatter: function (ms) {return $filter('date')(new Date(ms), 'dd/MM HH:mm')}},
y: {valueFormatter: function (num) {return num.toFixed(1)}}
},
xlabel: 'Local Time', ylabel: 'Temperature (ºC)', stepPlot: false};
};
提案、コメント、または回答を歓迎します。
ありがとう