谷歌地图api的setMap()无法正常工作

时间:2017-07-23 07:16:02

标签: javascript google-maps knockout.js

我正在使用Google Maps API构建地图,当我加载它时,我收到此错误:

  

未捕获的TypeError:无法读取属性' setMap'未定义的

我认为来自vm()的toggle()导致错误,但我不知道如何纠正错误。 我的目标是同时根据搜索显示标记。

以下是代码:



var locations = [
        {"name": "Marari Beach Alappuzha" ,'location': {'lat': 9.618406, 'lng': 76.340161} },
        {"name": "Tea Mueseum" ,'location': {'lat': 10.049198, 'lng': 77.051025 }},
        {"name": "Eravikulam National Park" ,'location': {'lat': 10.116233, 'lng': 77.067791} },
        {"name": "Chimmini Wildlife Sanctuary" ,'location': {'lat': 10.428646, 'lng': 76.491031} },
        {"name": "Bekal Fort ",'location': {'lat': 12.440895, 'lng': 75.030311 }}
      ]

var markers = [];
var map;
var boolean = [];
for(i=0;i<locations.length;i++){
    boolean[i] = true;
}
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        zoom: 7,
        center: {
            lat: 10.850516,
            lng: 76.271080
        }
    });
    var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    for (var i = 0; i < locations.length; i++) {
        var position = locations[i].location;
        var name = locations[i].name;
        var marker = new google.maps.Marker({
            // map:map,
            position: position,
            animation: google.maps.Animation.DROP,
            id: i
        });
        markers.push(marker);
        marker.addListener('click', (function(marker, i) {
            return function() {
                if (marker.getAnimation() != null) {
                    marker.setAnimation(null);
                } else {
                    marker.setAnimation(google.maps.Animation.BOUNCE);
                    stopAnimation(marker);
                }
            }
        })(marker, i));

        function stopAnimation(marker) {
            setTimeout(function() {
                marker.setAnimation(null);
            }, 3000);
        };
    }
    toggle();
}

function toggle(){
    for(g=0;g<locations.length;g++){
        if(boolean[g] === true){
            markers[g].setMap(map);
        }else if(boolean[g] === false){
            markers[g].setMap(null);
        }
    }
}

var z,g;
var vm = function(){
    var self = this;
    self.loc = ko.observableArray(locations);
    self.query = ko.observable('');
    self.filteredloc = ko.computed(function () {
        z=0;
    var filter = self.query().toLowerCase();
    console.log(boolean);
    toggle();
    if (!filter) {
        return self.loc();
    } else {
        return ko.utils.arrayFilter(self.loc(), function (item) {
            boolean[z] = item.name.toLowerCase().indexOf(filter) !== -1;
            // console.log(boolean[z]+'in pos'+z);
             z++;
            return item.name.toLowerCase().indexOf(filter) !== -1;
        });
    }
});

};

ko.applyBindings(new vm());
&#13;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compaitable" content="IE-edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Neighbourhood Map</title>
    <link rel="stylesheet" href="style.css">
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <script defer src="mapping.js"></script>
    <script asyc defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAZJYwSB-hwX7EXVNXtWo7HSjyPaJNmrWc&callback=initMap"></script>

</head>
<body>
    <div class="container">
        <div class="row">
            <div id="content" class="col-3">
                <div id="content_search">
                    <form action="#">
                        <input placeholder="Search…" type="search" name="q" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off">
                    </form>
                </div>
                <div class="content_data">
                    <ul id="content_data--style" data-bind="template: {name:'location', foreach:filteredloc}"></ul>
                </div>
            </div>
            <div class="col-9">
                <h3 >Neighbourhood Map</h3>
                <div id="map"></div>
            </div>
        </div>
    </div>
    <script type="text/html" id="location">
        <li>
            <strong data-bind="text: name"></strong>
        </li>
    </script>
</body>
</html> 
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我没有适合您的解决方案,但我想向您展示一些可以大大简化JavaScript代码的方法。

首先,我摆脱了单独的<em lang="en"></em>markers数组。相反,最好制作boolean数组元素的那些属性。毕竟,locations是您获取有关位置信息的地方,因此请将所有信息放在那里。在新代码中,每个locations数组元素都有locations属性(如果已创建标记)和marker属性,对应于前show数组元素。如果您不必更新单独的阵列,只需将所有信息保存在一个位置,事情就会变得更加简单。

我用boolean替换了几个for循环。 forEach()接受一个回调函数,这非常好,因为在这种情况下它会为传递给回调的forEach()参数提供一个闭包。因此,您不需要location中的复杂代码来创建闭包 - 闭包已经存在。

我通过删除和组合重复代码来简化marker.addListener()函数。

这就是我现在所有的时间,但我希望它会给你一些可以帮助你简化代码的东西 - 因为更简单的代码更容易理解和调试代码。

toggle()
var locations = [
    { "name": "Marari Beach Alappuzha" ,'location': { 'lat': 9.618406, 'lng': 76.340161 } },
    { "name": "Tea Mueseum" ,'location': { 'lat': 10.049198, 'lng': 77.051025 } },
    { "name": "Eravikulam National Park" ,'location': { 'lat': 10.116233, 'lng': 77.067791 } },
    { "name": "Chimmini Wildlife Sanctuary" ,'location': { 'lat': 10.428646, 'lng': 76.491031 } },
    { "name": "Bekal Fort ",'location': { 'lat': 12.440895, 'lng': 75.030311 } }
];

var map;

function initMap() {
    map = new google.maps.Map( document.getElementById('map'), {
        zoom: 7,
        center: {
            lat: 10.850516,
            lng: 76.271080
        }
    });
    var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    locations.forEach( function( location ) {
        var marker = location.marker = new google.maps.Marker({
            position: location.location,
            animation: google.maps.Animation.DROP
        });
        marker.addListener( 'click', function() {
            if( marker.getAnimation() ) {
                marker.setAnimation( null );
            } else {
                marker.setAnimation( google.maps.Animation.BOUNCE );
                stopAnimation( marker );
            }
        });

        function stopAnimation(marker) {
            setTimeout( function() {
                marker.setAnimation(null);
            }, 3000 );
        }
    });
    toggle();
}

function toggle() {
    locations.forEach( function( location ) {
        if( location.marker ) {
            location.marker.setMap( location.show ? map : null );
        }
    });
}

var vm = function() {
    var self = this;
    self.loc = ko.observableArray( locations );
    self.query = ko.observable('');
    self.filteredloc = ko.computed( function () {
        var z = 0;
        var filter = self.query().toLowerCase();
        toggle();
        if( ! filter ) {
            return self.loc();
        } else {
            return ko.utils.arrayFilter( self.loc(), function( item ) {
                boolean[z] = item.name.toLowerCase().indexOf(filter) !== -1;
                // console.log(boolean[z]+'in pos'+z);
                z++;
                return item.name.toLowerCase().indexOf(filter) !== -1;
            });
        }
    });
}

ko.applyBindings( new vm() );