Bounce a pin in google maps once

2019-01-30 20:07发布

I want to bounce a pin on a google map once. The following code will make the marker bounce but it just keeps going...

myPin.setAnimation(google.maps.Animation.BOUNCE);

Then calling

myPin.setAnimation(null);

makes the animation stop. Setting a timeout works but the duration of a bounce doesn't look like it is a round number so doing this

  setTimeout(function(){ myPin.setAnimation(null); }, 1000);

Make the bounce animation end prematurely and look terrible.

Does anyone know of a better way to accomplish this?

9条回答
beautiful°
2楼-- · 2019-01-30 20:30

I have found that in order for a pin to stop animating after a bounce is completed, you need to make the pin draggable. The best way I have found to do this is by using two timeouts:

  1. to remove the animation before the first bounce is complete.
  2. to make the marker not draggable after the first bounce is complete.

Animations will stop once you make a marker not draggable. I have created a plunker to show what I mean: http://plnkr.co/edit/Gcns3DMklly6UoEJ63FP?p=preview

The HTML

    <div id="map-canvas"></div>
    <p>
      Bounce marker
      <select id="bounceNumber">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
      </select>
      times.
      <button onclick="bounceMarker()">Go!</button>
    </p>

The JavaScript

var marker = null,
    toBounce = null,
    toDrag = null;

function initialize() {
    var mapOptions = {
        zoom: 4,
        center: new google.maps.LatLng(-25.363882, 131.044922)
    };
    var map = new google.maps.Map(document.getElementById('map-canvas'),
        mapOptions);
    marker = new google.maps.Marker({
        position: new google.maps.LatLng(-25.363882, 131.044922),
        map: map
    });
}

function bounceMarker() {
    var select = document.getElementById("bounceNumber"),
        bounces = parseInt(select.options[select.selectedIndex].value),
        animationTO = (bounces - 1) * 700 + 350,
        dragTO = animationTO + 1000;

    // Bounce the marker once
    if (marker.getAnimation() !== null) {
        marker.setAnimation(null);
        clearTimeout(toBounce);
        clearTimeout(toDrag);
        setTimeout(function () {
            marker.setDraggable(false);
        }, 750);
    } else {
        // Workaround to make marker bounce once.
        // The api will finish the current bounce if a marker is set to draggable.
        // So use two timeouts:
        // 1. to remove the animation before the first bounce is complete.
        // 2. to make the marker not draggable after the first bounce is complete.
        // Animations will stop once you make a marker not draggable.
        marker.setDraggable(true);
        marker.setAnimation(google.maps.Animation.BOUNCE);
        toBounce = setTimeout(function () {
            marker.setAnimation(null);
        }, animationTO);
        toDrag = setTimeout(function () {
            marker.setDraggable(false);
        }, dragTO);
    }
}


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

For as far as I am aware this works cross browser. I have tested in chrome, firefox, safari & opera. I haven't tested this in internet explorer yet.

查看更多
爷、活的狠高调
3楼-- · 2019-01-30 20:32

This is a tough one with no perfect answer yet because, while 750ms works fine for a desktop browser, it does look stunted on a mobile device. Google has not really added much to the animation API, so there's no solutions via API.

The best I've been able to accomplish is to set the timeout value to 900ms, it looks the same on Desktop because it exploits the 150ish ms that the icon pauses between each bounce, and gives a laggy mobile device some extra breathing space for animation time.

Edit: My solution stopped working for me suddenly. Oops. If you're doing this on mobile, might just be best to not bother with the bounce at all.

查看更多
淡お忘
4楼-- · 2019-01-30 20:36

Okay none of the other answers quite worked well enough given the limitations of the API. So here's what I've found.

  • Each bounce is about 700ms as of google maps version js?v=3.13.
  • Calling marker.setAnimation(null) stops the marker from bouncing only after it completes the current bounce. So if you wait until 710ms have expired in the bounce sequence and then set marker.setAnimation(null), the API will continue to perform an additional bounce without interrupting its current bounce sequence.
  • However, if you then immediately call setAnimation(700) again on that same marker it will interrupt the current bounce sequence. Not exactly pretty.
  • Also note, that if you're decorating the marker with an overlay of some sort, it won't bounce those items as they are not attached to the marker.

Simple case (as seen in the other answers):

marker.setAnimation(google.maps.Animation.BOUNCE);
setTimeout(function () {
    marker.setAnimation(null);
}, 700); // current maps duration of one bounce (v3.13)

Assuming that:

  1. the bouncing occurs from user interaction
  2. and you don't want to truncate a current bounce sequence when the user triggers another one on the same object
  3. and you don't want to discard that request to perform another bounce sequence,

you can use setTimout in conjunction with jquery's .queue method to prevent a new bounce request from interrupting the current one, but still queuing it up to perform the bounce sequence after the current one completes. (note: I used two bounces instead of one so msec is set to 1400).

more realistic case:

// bounce markers on hover of img
$('#myImage').hover(function () {
    // mouseenter
    var marker = goGetMarker();
    function bounceMarker()
    {
        marker.setAnimation(google.maps.Animation.BOUNCE);
        setTimeout(function ()
        {
            marker.setAnimation(null);
            $(marker).dequeue();
        }, 1400); // timeout value lets marker bounce twice before deactivating
    }

    // use jquery queue
    if ($(marker).queue().length <= 1) // I'm only queuing up 1 extra bounce
        $(marker).queue(bounceMarker);
}, function () {
    // mouseleave
    var marker = goGetMarker();
    marker.setAnimation(null);
});
查看更多
登录 后发表回答