【问题标题】:Change icon on mouseover/out fails鼠标悬停/移出时更改图标失败
【发布时间】:2014-05-31 22:25:02
【问题描述】:

我对这段代码感到很恼火。正如您可能猜到的那样,我对编码比较陌生。我将不胜感激您对它为什么不起作用的任何见解。

我正在尝试更改鼠标悬停/移出时的标记图标。我正在尝试在 for 循环中创建和添加侦听器。在循环中,从位置数组创建标记并将其推送到另一个数组,为 mouseover 事件添加一个侦听器以更改图标,并为 mouseout 事件添加另一个侦听器以使标记图标无效。下面的代码显示了地图,添加了标记,并且似乎在监听 mouseover 和 mouseout 事件(光标悬停在标记上时会发生变化),但图标不会在这些事件中发生变化。

    function initialize(){  
        //Marker locations
        var NYC = new google.maps.LatLng(40.721505, -74.004783);
        var LA = new google.maps.LatLng(34.049519, -118.238698);
        var Chicago = new google.maps.LatLng(41.877461, -87.624352);
        var Seattle = new google.maps.LatLng(47.606747, -122.330349);
        var Miami = new google.maps.LatLng(25.788661, -80.226617);
        var Boston = new google.maps.LatLng(42.357913, -71.059217);
        var Houston = new google.maps.LatLng(29.758182, -95.364213);
        var KansasCity = new google.maps.LatLng(39.097781,-94.588079);
        var locations = new Array(NYC, LA, Chicago, Seattle, Miami, Boston, Houston, KansasCity);

        //Array to store markers
        var markers = new Array ();

        //Icon
        var gif = 'http://demers-ambulances.com/assets/img/news/mapPinOver2.gif';

        //Map options
        var mapOptions = {
            center: KansasCity,
            zoom: 5,
            zoomControl: true,
            zoomControlOptions: {
                style: google.maps.ZoomControlStyle.SMALL,
                position: google.maps.ControlPosition.TOP_LEFT
            },
            mapTypeControl: true,
            mapTypeControlOptions: {
                style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
                position: google.maps.ControlPosition.TOP_RIGHT,
            },
        };

        //Create map
        var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions); 

        //Create markers and add listener to change marker icon on mouseover/out
        for (i = 0; i<locations.length; i++){
            var marker = new google.maps.Marker({
                position: locations[i],
                draggable: true,                
                map: map,
            });
            markers.push(marker);               
            google.maps.event.addListener(markers[i], 'mouseover', function() {
                markers[i].setIcon(gif);
            });
            google.maps.event.addListener(markers[i], 'mouseout', function() {
                markers[i].setIcon(null);
            });         
        };          
    };

    google.maps.event.addDomListener(window, 'load', initialize);

感谢您的帮助:)

【问题讨论】:

标签: javascript google-maps google-maps-api-3 mouseover mouseout


【解决方案1】:

关闭问题:报错:

Uncaught TypeError: Cannot read property 'setIcon' of undefined

代码必须改为:

        (function(i) {
            google.maps.event.addListener(markers[i], 'mouseover', function() {
                markers[i].setIcon(gif);
            });

            google.maps.event.addListener(markers[i], 'mouseout', function() {
                markers[i].setIcon(null);
            });         
        })(i);

【讨论】:

  • 谢谢安托!这就像一个魅力。我是编程新手,但感谢像你这样的人,我学得很快!我真的很感激。
  • 试图支持您的评论,但我没有声誉!我对 SO :\ 是全新的。对不起安托...再次感谢。
【解决方案2】:

基本上问题出在这里:

    for (i = 0; i<locations.length; i++){
        var marker = new google.maps.Marker({
            position: locations[i],
            draggable: true,                
            map: map,
        });
        markers.push(marker);               
        google.maps.event.addListener(markers[i], 'mouseover', function() {
            markers[i].setIcon(gif);
        });
        google.maps.event.addListener(markers[i], 'mouseout', function() {
            markers[i].setIcon(null);
        });         
    };          

这段代码看起来很无辜,但问题在于,一旦循环完成执行并调用我们的事件侦听器,变量i 已经等于locations.length

所以每当调用事件监听器时,i 已经更改为 locations.length,而markers[i] 将返回 undefined,因为最后一个推送索引是 i = locations.length - 1 因为循环条件是i&lt;locations.length

由于在调用事件监听器时markers[i]是未定义的,那么它将抛出以下错误,因为它不再具有setIcon方法:TypeError: Cannot read property 'setIcon' of undefined

要解决这个问题,您应该在闭包中捕获i 的值(如上面的Anto Jurković described,不要忘记给他投票):

    (function(i) {
        google.maps.event.addListener(markers[i], 'mouseover', function() {
            markers[i].setIcon(gif);
        });

        google.maps.event.addListener(markers[i], 'mouseout', function() {
            markers[i].setIcon(null);
        });         
    })(i);

这里我们在每个循环上创建一个函数并立即使用i 调用它,因此i 的值被捕获在闭包中,并且由于javascript函数具有块范围(循环没有),变量@987654339 @ 对于循环的每次迭代都是相同的。

问题及其解决方案也在以下问题中描述:Javascript closure inside loops - simple practical example

【讨论】:

  • 法里德,感谢您的详尽解释!不胜感激。在旁注中,我试图支持安托的评论,但我没有任何声誉......
【解决方案3】:

在进一步试验了AntoFarid 推荐的代码后,我找到了另一个解决方案。对于此解决方案,在初始化函数之外创建一个函数以将侦听器添加到标记,然后在 for 循环中创建每个标记时调用。如果您对此有任何想法,请在下面发表评论。我不知道这是否是一个好方法,我只知道它有效:)

        for (i = 0; i<locations.length; i++){
            var marker = new google.maps.Marker({
                position: locations[i],
                draggable: true,                
                map: map,
            });
            animateit(marker);
            markers.push(marker);               
        };          
    };


    function animateit(marker) {
                google.maps.event.addListener(marker, 'mouseover', function() {
                    marker.setIcon(gif);
                });

                google.maps.event.addListener(marker, 'mouseout', function() {
                    marker.setIcon(null);
                }); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 2012-02-10
    • 2011-07-09
    • 1970-01-01
    • 2010-11-30
    相关资源
    最近更新 更多