AngularJS 使用 ng-map 实现动态热图可视化
AngularJS with ng-map to implement dynamic heatmap visualization
大家好,我是前端开发的绝对新手,这是我第一次使用 AngularJS 之类的东西,说实话,我认为这真的很难,而且我真的没有太多清晰的想法关于它是如何工作的。我正在从事一个项目,旨在可视化 Google 地图上的一批坐标。我已经在服务器端构建了相应的 API 并且它工作正常。
我在我的项目中使用 ng-map 下面是我的 main.html:
代码的第一个版本
<div class="screen-wrapper" id="map-wrapper">
<div map-lazy-load="https://maps.google.com/maps/api/js">
<ng-map center="37.782551, -122.445368" zoom="3" disable-default-u-i="true">
<heatmap-layer id="foo" data="dummyData"></heatmap>
</ng-map>
</div>
</div>
上面的dummyData是一个硬编码在外部JS文件中的数组,我原本认为不需要,但后来当我试图从地图中获取heatmapLayer时,我发现这很重要。没有这个属性,我无法在我的控制器中获取 heatmapLayer。这有点奇怪,但我只是不知道为什么会这样。
下面是我的main.controller.js:
(function() {
'use strict';
angular
.module('webapp')
.controller('MainController', MainController);
/** @ngInject */
function MainController(NgMap, $scope, $http) {
var resp = $http.get('url.to.api')
.then(function(result) {
return result.data;
});
var incidentData = []
var extractor = Promise.resolve(resp).then(function(data) {
for (var i = 0; i < data.length; i++) {
var lat = data[i]["lat"];
var lon = data[i]["lon"];
incidentData.push(new google.maps.LatLng(lat,lon));
}
}).then(function() {
var incidentArray = new google.maps.MVCArray(incidentData);
var heatMapLayer = new google.maps.visualization.HeatmapLayer({
data: incidentArray,
radius: 20
});
var heatmap;
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
});
}
})();
上面我想做的是做一个 HTTP 请求来取回纬度和经度。由于是"Promise"的格式,所以我要把它们提取出来放到一个数组中。在我看来,一切似乎都还好,但它根本不起作用。该界面仅显示 'hard-coded' 可视化,不显示新的 heatMapLayer。
任何人都可以建议 direction/solution 来解决我上面提到的问题吗?感谢大家和 Whosebug。
update 在 Daniel 的建议下,我对我的代码进行了以下修改。
在main.controller.js我改了代码段:
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
至:
$scope.$apply(function() {
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
});
再次感谢丹尼尔!
您可能正在绕过 angular 的摘要循环。这意味着您的更改已经完成,但尚未显示。
Angular 自行跟踪所有更改,并在发生更改时更新视图。每当您手动更改某些内容而不被 angular 跟踪(例如通过 ng-bind 或 {{ }} 中的变量跟踪)时,您需要调用 scope.$apply() 以手动触发摘要循环。通常,当 angular 自动执行此操作时,您甚至不会注意到(或需要知道)。例如 $http 也会处理这个问题。
不过,这里
var resp = $http.get('url.to.api')
.then(function(result) {
return result.data;
});
我怀疑 scope.$digest() 在回调之后已经被调用了(那时你还没有改变任何东西)。
var extractor = Promise.resolve(resp).then(function(data) {
在您的第二个 .then() 回调中,您进行了更改,但它们将不再显示。
我建议将下面的代码放入第一个 .then() 回调中。如果这不可能,您将必须在更改完成后手动调用 scope.$apply()。
大家好,我是前端开发的绝对新手,这是我第一次使用 AngularJS 之类的东西,说实话,我认为这真的很难,而且我真的没有太多清晰的想法关于它是如何工作的。我正在从事一个项目,旨在可视化 Google 地图上的一批坐标。我已经在服务器端构建了相应的 API 并且它工作正常。
我在我的项目中使用 ng-map 下面是我的 main.html:
代码的第一个版本<div class="screen-wrapper" id="map-wrapper">
<div map-lazy-load="https://maps.google.com/maps/api/js">
<ng-map center="37.782551, -122.445368" zoom="3" disable-default-u-i="true">
<heatmap-layer id="foo" data="dummyData"></heatmap>
</ng-map>
</div>
</div>
上面的dummyData是一个硬编码在外部JS文件中的数组,我原本认为不需要,但后来当我试图从地图中获取heatmapLayer时,我发现这很重要。没有这个属性,我无法在我的控制器中获取 heatmapLayer。这有点奇怪,但我只是不知道为什么会这样。
下面是我的main.controller.js:
(function() {
'use strict';
angular
.module('webapp')
.controller('MainController', MainController);
/** @ngInject */
function MainController(NgMap, $scope, $http) {
var resp = $http.get('url.to.api')
.then(function(result) {
return result.data;
});
var incidentData = []
var extractor = Promise.resolve(resp).then(function(data) {
for (var i = 0; i < data.length; i++) {
var lat = data[i]["lat"];
var lon = data[i]["lon"];
incidentData.push(new google.maps.LatLng(lat,lon));
}
}).then(function() {
var incidentArray = new google.maps.MVCArray(incidentData);
var heatMapLayer = new google.maps.visualization.HeatmapLayer({
data: incidentArray,
radius: 20
});
var heatmap;
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
});
}
})();
上面我想做的是做一个 HTTP 请求来取回纬度和经度。由于是"Promise"的格式,所以我要把它们提取出来放到一个数组中。在我看来,一切似乎都还好,但它根本不起作用。该界面仅显示 'hard-coded' 可视化,不显示新的 heatMapLayer。
任何人都可以建议 direction/solution 来解决我上面提到的问题吗?感谢大家和 Whosebug。
update 在 Daniel 的建议下,我对我的代码进行了以下修改。
在main.controller.js我改了代码段:
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
至:
$scope.$apply(function() {
$scope.$on('mapInitialized', function(event, map) {
heatMapLayer.setMap(map.instance);
});
});
再次感谢丹尼尔!
您可能正在绕过 angular 的摘要循环。这意味着您的更改已经完成,但尚未显示。
Angular 自行跟踪所有更改,并在发生更改时更新视图。每当您手动更改某些内容而不被 angular 跟踪(例如通过 ng-bind 或 {{ }} 中的变量跟踪)时,您需要调用 scope.$apply() 以手动触发摘要循环。通常,当 angular 自动执行此操作时,您甚至不会注意到(或需要知道)。例如 $http 也会处理这个问题。
不过,这里
var resp = $http.get('url.to.api')
.then(function(result) {
return result.data;
});
我怀疑 scope.$digest() 在回调之后已经被调用了(那时你还没有改变任何东西)。
var extractor = Promise.resolve(resp).then(function(data) {
在您的第二个 .then() 回调中,您进行了更改,但它们将不再显示。
我建议将下面的代码放入第一个 .then() 回调中。如果这不可能,您将必须在更改完成后手动调用 scope.$apply()。