点击项目动画并在谷歌地图上显示相关标记的信息窗口

时间:2017-08-13 13:07:24

标签: javascript google-maps google-maps-api-3 knockout.js

代码说明

1.在viewModel中声明class UserActivity : AppCompatActivity(), UserClickCallbacks { // your activity code override fun onUserClick(user: User) { // but the user click event logic here // This triggered when user in tha adapter clicked } } 函数,其中一个参数为animateMarker

2.在viewModel中声明marker,其中包含三个参数(marker,infowindow,element)和调用populateInfoWindow函数。

3.call animateMarker内部点击事件监听器内部迭代位置的循环。

4.added data-bind:"点击:$ root.populateInfoWindow"到populateInfoWindow

错误

  

无法读取属性'标题'未定义的

此外,既没有动画标记也没有infowindo。同时单击列表项。 是否有其他推荐的方法可以解决这个问题或想法。

app.js

// model包含有关位置的必需数据

<li  data-bind : "click : $root.populateInfoWindow >

的index.html

var model = [

    {
        title: 'Park Ave Penthouse',
        latLng: {
            lat: 40.7713024,
            lng: -73.9632393
        }
    },
    {
        title: 'Chelsea Loft',
        latLng: {
            lat: 40.7444883,
            lng: -73.9949465
        }
    },
    {
        title: 'Union Square Open Floor Plan',
        latLng: {
            lat: 40.7347062,
            lng: -73.9895759
        }
    },
    {
        title: 'East Village Hip Studio',
        latLng: {
            lat: 40.7281777,
            lng: -73.984377
        }
    },
    {
        title: 'TriBeCa Artsy Bachelor Pad',
        latLng: {
            lat: 40.7195264,
            lng: -74.0089934
        }
    },
    {
        title: 'Chinatown Homey Space',
        latLng: {
            lat: 40.7180628,
            lng: -73.9961237
        }
    }

];
//declaring global variables 
var infoWindow, map;

function initMap() {
    //initialize the map
    map = new google.maps.Map(document.getElementById('map'), {
        center: model[3].latLng,
        zoom: 12
    });


    myViewModel = new ViewModel();
    ko.applyBindings(myViewModel)

};



function ViewModel() {

    var self = this;
    this.filter = ko.observable();
    this.places = ko.observableArray(model);
    self.infowindow = new google.maps.InfoWindow();

    // self.marker = [];
    model.forEach(function(element) {
        var position = element.latLng;
        var title = element.title;

        element.marker = new google.maps.Marker({
            position: position,
            title: title,
            map: map,
            animation: google.maps.Animation.DROP,
        });
        // self.marker.push(element.marker);
        element.marker.addListener('click', function() {
            self.populateInfoWindow(this, self.infowindow, element);
        });

    });

    self.populateInfoWindow = (function(marker, infowindow, element) {

        self.infowindow.setContent('<div><strong>' + element.title + '</strong><br>');
        self.infowindow.open(map, marker);
        self.animateMarker(marker);

    });
    self.animateMarker = (function(marker) {
        marker.setAnimation(google.maps.Animation.BOUNCE);
        setTimeout(function() {
            marker.setAnimation(null)
        }, 1500);
    });
    this.visibleLocations = ko.computed(function() {
        var filter = self.filter();
        if (!filter) {
            ko.utils.arrayForEach(self.places(), function(item) {
                item.marker.setVisible(true);
            });
            return self.places();
        } else {
            return ko.utils.arrayFilter(self.places(), function(item) {
                // set all markers visible (false)
                var result = (item.title.toLowerCase().search(filter) >= 0);
                item.marker.setVisible(result);
                return result;
            });
        }

    });

};

//loading google maps error handling 

function googleError() {

    alert("check your internet connection and reload the page");


}

1 个答案:

答案 0 :(得分:1)

由于InfoWindow.open方法需要MVCObject对象(本例中为标记对象)作为第二个参数,因此需要更改click事件绑定:

data-bind="click: $root.populateInfoWindow"

到这一个:

data-bind="click: $root.populateInfoWindow.bind(this,$data.marker,$root.infowindow)"
  

这种方式(通过bind functionmarkerinfoWindow   参数传递给populateInfoWindow函数

修改后的示例

&#13;
&#13;
var model = [

    {
        title: 'Park Ave Penthouse',
        latLng: {
            lat: 40.7713024,
            lng: -73.9632393
        }
    },
    {
        title: 'Chelsea Loft',
        latLng: {
            lat: 40.7444883,
            lng: -73.9949465
        }
    },
    {
        title: 'Union Square Open Floor Plan',
        latLng: {
            lat: 40.7347062,
            lng: -73.9895759
        }
    },
    {
        title: 'East Village Hip Studio',
        latLng: {
            lat: 40.7281777,
            lng: -73.984377
        }
    },
    {
        title: 'TriBeCa Artsy Bachelor Pad',
        latLng: {
            lat: 40.7195264,
            lng: -74.0089934
        }
    },
    {
        title: 'Chinatown Homey Space',
        latLng: {
            lat: 40.7180628,
            lng: -73.9961237
        }
    }

];
//declaring global variables 
var infoWindow, map;

function initMap() {
    //initialize the map
    map = new google.maps.Map(document.getElementById('map'), {
        center: model[3].latLng,
        zoom: 12
    });


    myViewModel = new ViewModel();
    ko.applyBindings(myViewModel)

};



function ViewModel() {

    var self = this;
    this.filter = ko.observable();
    this.places = ko.observableArray(model);
    self.infowindow = new google.maps.InfoWindow();

    // self.marker = [];
    model.forEach(function (element) {
        var position = element.latLng;
        var title = element.title;

        element.marker = new google.maps.Marker({
            position: position,
            title: title,
            map: map,
            animation: google.maps.Animation.DROP,
        });
        // self.marker.push(element.marker);
        element.marker.addListener('click', function () {
            self.populateInfoWindow(this, self.infowindow, element);
        });

    });

    self.populateInfoWindow = (function (marker, infowindow, element) {

        self.infowindow.setContent('<div><strong>' + marker.title + '</strong><br>');
        self.infowindow.open(map, marker);
        self.animateMarker(marker);

    });
    self.animateMarker = (function (marker) {
        marker.setAnimation(google.maps.Animation.BOUNCE);
        setTimeout(function () {
            marker.setAnimation(null)
        }, 1500);
    });
    this.visibleLocations = ko.computed(function () {
        var filter = self.filter();
        if (!filter) {
            ko.utils.arrayForEach(self.places(), function (item) {
                item.marker.setVisible(true);
            });
            return self.places();
        } else {
            return ko.utils.arrayFilter(self.places(), function (item) {
                // set all markers visible (false)
                var result = (item.title.toLowerCase().search(filter) >= 0);
                item.marker.setVisible(result);
                return result;
            });
        }

    });

};

google.maps.event.addDomListener(window, 'load', initMap);
&#13;
#map {
            height: 140px;
 }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>

<script src="https://maps.googleapis.com/maps/api/js"></script>
<script type="text/javascript" src="app.js"></script>


<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ"
    crossorigin="anonymous">
<link href="style.css" rel="stylesheet">


<div class="search-menu ">
    <nav class="navbar navbar-light bg-faded justify-content-between">
        <h1 class="navbar-brand"> Find your favorite place</h1>
        <form class="form-inline">
            <input class="form-control mr-sm-2" type="text" placeholder="Search" data-bind="textInput: filter">
        </form>
    </nav>

    <ul class="list-group" data-bind="foreach: visibleLocations">
        <li class="list-group-item list-group-item-action" data-bind="text: title, click: $root.populateInfoWindow.bind(this,$data.marker,$root.infowindow)"></li>
    </ul>
</div>


<div id="map"></div>
&#13;
&#13;
&#13;