动态添加时,第二个Google Map无法正确呈现

时间:2014-05-30 14:37:45

标签: javascript html angularjs google-maps angular-ui-bootstrap

以下HTML在复制到 .html 文件并在浏览器中直接查看时会显示我的问题。

<!DOCTYPE HTML>
<html ng-app="myApp">

<head>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular.min.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.min.js"> </script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"> </script>

<script>

    var mapOptions = {
        zoom: 5,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
    };

    var myApp = angular.module('myApp', ['ui.bootstrap']);

    var myController = function($scope){
        $scope.locations = [];

        $scope.addLocation = function(){
            var id = $scope.locations.length+1;

            $scope.locations.push({ id: id, city: $scope.newLocation.city, country: $scope.newLocation.country });

            $scope.newLocation = { city:'', country:'' };
        }

        $scope.$watch('locations', function(){

            for(var i = 0; i < $scope.locations.length; i++){
                var thisLocation = $scope.locations[i];

                if(!thisLocation.rendered){
                    var geocoder = new google.maps.Geocoder();

                    var id = thisLocation.id;
                    var address = thisLocation.city + ' ' + thisLocation.country;

                    geocoder.geocode({ 'address': address }, function (results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            var longitude = results[0].geometry.location.A;
                            var latitude = results[0].geometry.location.k;

                            var map = $scope.displayMap(latitude, longitude, 'Test' + id, id);
                            google.maps.event.trigger(map, "resize");
                        }
                    });

                    thisLocation.rendered = true;
                }


            }

        }, true);

        $scope.displayMap = function displayMap(latitude, longitude, name, id) {

            var mapDiv = document.getElementById('map' + id);
            if (mapDiv) mapDiv.style.display = "block";

            var mapCanvas = document.getElementById('map-canvas' + id);
            if (mapCanvas) mapCanvas.style.height = "400px";

            var map = new google.maps.Map(document.getElementById('map-canvas' + id), mapOptions);

            var locCoords = new google.maps.LatLng(latitude, longitude);

            map.setCenter(locCoords);

            new google.maps.Marker({
                position: locCoords,
                map: map,
                title: name
            });

            return map;
        }

        $scope.newLocation = { city:'', country:'' };
    }

    myController.$inject = ['$scope'];
    myApp.controller('myController', myController);
</script>

</head>

<body ng-controller="myController">

<form ng-submit="addLocation()">
    <label for="city"><input id="city" ng-model="newLocation.city" required /></label>
    <label for="country"><input id="country" ng-model="newLocation.country" required /></label>
    <input type="submit" value="Submit" />
</form>

<tabset>
    <tab ng-repeat="location in locations" heading="{{location.city}}">
        <div id="map{{location.id}}" class="map">
            <div id="map-canvas{{location.id}}" class="map-canvas">
                Map goes here
            </div>
        </div>
    </tab>
</tabset>

</body>

</html>

基本上,您填写表单一次,以向tabset添加地图,它可以正常工作:

First map looking fine

再次填写表格以添加第二张地图,这是一场灾难:

Second map, disaster zone

Chrome的开发者控制台中没有任何内容表明存在任何问题。

我无法弄清楚这是Google Maps问题,Angular问题还是针对引导程序问题的Angular指令,所以我使用这三个模拟了这个模拟,并尽可能地模仿我的实际代码。

有人可以了解这里发生的事情吗?

由于

2 个答案:

答案 0 :(得分:1)

好吧事实证明Google地图无法处理非活动标签上的渲染,所以我需要创建标签并在渲染地图之前将其设置为活动状态。

我改变了:

$scope.locations.push({ id: id, city: $scope.newLocation.city, country: $scope.newLocation.country });

要:

$scope.locations.push({ id: id, city: $scope.newLocation.city, country: $scope.newLocation.country, active: true });

在for循环结束时添加了以下内容:

thisLocation.active = true;

当您将其设置为true时,Angular似乎足够智能将其他标签的活动属性设置为false。

最后,我将tab元素的active属性设置为模型的active属性:

<tab ng-repeat="location in locations" heading="{{location.city}}" active="location.active" >

以下是一个工作示例:

<!DOCTYPE HTML>
<html ng-app="myApp">

<head>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular.min.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.10.0/ui-bootstrap-tpls.min.js"> </script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"> </script>

<script>

    var mapOptions = {
        zoom: 5,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
    };

    var myApp = angular.module('myApp', ['ui.bootstrap']);

    var myController = function($scope){
        $scope.locations = [];

        $scope.addLocation = function(){
            var id = $scope.locations.length+1;

            $scope.locations.push({ id: id, city: $scope.newLocation.city, country: $scope.newLocation.country, active: true });

            $scope.newLocation = { city:'', country:'' };
        }

        $scope.$watch('locations', function(){

            for(var i = 0; i < $scope.locations.length; i++){
                var thisLocation = $scope.locations[i];

                if(!thisLocation.rendered){ 

                    var geocoder = new google.maps.Geocoder();

                    var id = thisLocation.id;
                    var address = thisLocation.city + ' ' + thisLocation.country;

                    geocoder.geocode({ 'address': address }, function (results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            var longitude = results[0].geometry.location.A;
                            var latitude = results[0].geometry.location.k;

                            var map = $scope.displayMap(latitude, longitude, 'Test' + id, id);
                            google.maps.event.trigger(map, "resize");
                        }
                    });

                    thisLocation.active = true;
                    thisLocation.rendered = true;
                }


            }

        }, true);

        $scope.displayMap = function displayMap(latitude, longitude, name, id) {

            var mapDiv = document.getElementById('map' + id);
            if (mapDiv) mapDiv.style.display = "block";

            var mapCanvas = document.getElementById('map-canvas' + id);
            if (mapCanvas) mapCanvas.style.height = "400px";

            var map = new google.maps.Map(document.getElementById('map-canvas' + id), mapOptions);

            var locCoords = new google.maps.LatLng(latitude, longitude);

            map.setCenter(locCoords);

            new google.maps.Marker({
                position: locCoords,
                map: map,
                title: name
            });

            google.maps.event.trigger(map, "resize");

            return map;
        }

        $scope.newLocation = { city:'', country:'' };
    }

    myController.$inject = ['$scope'];
    myApp.controller('myController', myController);
</script>

</head>

<body ng-controller="myController">

<form ng-submit="addLocation()">
    <label for="city"><input id="city" ng-model="newLocation.city" required /></label>
    <label for="country"><input id="country" ng-model="newLocation.country" required /></label>
    <input type="submit" value="Submit" />
</form>

<tabset>
    <tab ng-repeat="location in locations" heading="{{location.city}}" active="location.active" >
        <div id="map{{location.id}}" class="map">
            <div id="map-canvas{{location.id}}" class="map-canvas">
                Map goes here
            </div>
        </div>
    </tab>
</tabset>

</body>

</html>

答案 1 :(得分:0)

尝试触发调整大小:

google.maps.event.trigger(map, "resize");