как анимировать маркер для каждой координаты на Mapbox? - PullRequest
0 голосов
/ 29 февраля 2020

Я использую mapbox draw и пытаюсь анимировать маркер для каждой координаты, этот код я использую для получения координат.

map.on('draw.modechange', function(e) { 
   map.on('click', function(e) {
     if (draw.getMode() == 'draw_polygon') {
        lon = e.lngLat.lng;
        lat = e.lngLat.lat;
        //var gps = {};
        //var gps = JSON.stringify(e.lngLat.wrap());

        var marker = new mapboxgl.Marker();

            function animateMarker(timestamp) {
            var radius = 20;


            marker.setLngLat([lon,lat]);

            marker.addTo(map);


            requestAnimationFrame(animateMarker);
            }

        requestAnimationFrame(animateMarker);

       };
    });
 });

Это код, который я сделал для анимации маркера Каждые координаты и я нажал на карту, и есть маркер, но вместо этого я пытаюсь анимировать маркер, чтобы перейти к каждой точке, которую я нажал, поэтому я добавил кнопку.

   var marker = new mapboxgl.Marker();

              function animateMarker(timestamp) 
           {
              var radius = 20;

              marker.setLngLat([lon,lat]);

              marker.addTo(map);

              requestAnimationFrame(animateMarker);
            }

        requestAnimationFrame(animateMarker);

модифицированный код, который я добавил кнопка с функцией onclick

 <button id="anim" onclick="animateMarker()">subimit</button>

1 Ответ

1 голос
/ 01 марта 2020

Вам нужно использовать Turf JS (https://turfjs.org/) и requestAnimationFrame. Я делаю это так. Но в этом коде новая анимация не может начаться, пока не закончится предыдущая. Вы можете попробовать исправить это для себя.

Прежде всего, вам нужно добавить источник маркера и объект маркера после первого щелчка, например, так:

map.on('click', function(event) {
    map.addSource('point_source', {
        'type': 'geojson',
        'data': {
           'type': 'Point',
           'coordinates': [event.lngLat.lng, event.lngLat.lat]
        }
    });

    map.addLayer({
        'id': 'point',
        'source': 'point_source',
        'type': 'circle',
        'paint': {
            'circle-radius': 10,
            'circle-color': '#007cbf'
        }
    });
);

После этого вы вызываете requestAnimationFrame с обратным вызовом. функция, которая оживляет маркер и делает рекурсию. Методу обратного вызова передается единственный аргумент, который указывает текущее время после загрузки страницы. При обратном вызове используйте Turf.along, он берет LineString и возвращает Point на указанном расстоянии вдоль линии и устанавливает его в Sourcebox объекта mapbox. Для указанного расстояния вы можете использовать переданный аргумент (после загрузки страницы), для LineString использовать начальную и конечную точки.

var start_data = null;
var destination_data = null;
var start_time = null;

function animateMarker(tm) {
    if(start_time === null) {
        start_time = tm;
    }


    var speed = 2; //change this for make animation faster of slower
    distance = (tm - start_time) / speed;
    var newPoint = turf.along(turf.lineString([start_data.coordinates,destination_data.coordinates]), distance);

    if(!(newPoint.geometry.coordinates == destination_data.coordinates)){
        //set new position and do recursion
        map.getSource('point_source').setData(newPoint);
        requestAnimationFrame(animateMarker);
    } else {
        start_time = null;
    }

}

Это мой полный код. Не забудьте вставить свой accessToken.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Animate a point</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/Turf.js/5.1.5/turf.js" integrity="sha256-YcmHZHyXpKYagiKb3z5qKGALna6dDVK4NP+4GTOzh6k=" crossorigin="anonymous"></script>
<style>
    body { margin: 0; padding: 0; }
    #map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
    mapboxgl.accessToken = '*API_KEY*';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [0, 0],
zoom: 2
});

var start_data = null;
var current_data = null;
var destination_data = null;
var start_time = null;
var isAnimated = false;

function getPointData(lngLat) {
    return {
        'type': 'Point',
        'coordinates': [lngLat.lng, lngLat.lat]
    };
}

function animateMarker(tm) {
    if(start_time === null) {
        start_time = tm;
    }

    zero_time = tm - start_time;
    var newPoint = turf.along(turf.lineString([start_data.coordinates,destination_data.coordinates]), (zero_time / 2));

    if(!(newPoint.geometry.coordinates == destination_data.coordinates)){
        current_data = newPoint.geometry;
        map.getSource('point_source').setData(newPoint);
        requestAnimationFrame(animateMarker);
    } else {
        isAnimated = false;
        start_time = null;
    }

}

map.on('click', function(event) {
    var coordsClick = getPointData(event.lngLat);

    if(map.getSource('point_source') && !isAnimated){
        isAnimated = true;
        start_data = current_data;
        destination_data = coordsClick;

        requestAnimationFrame(animateMarker);
    }
    if(map.getSource('point_source') === undefined) {
        current_data = coordsClick;
        destination_data = coordsClick;

        map.addSource('point_source', {
            'type': 'geojson',
            'data': coordsClick
        });

        map.addLayer({
            'id': 'point',
            'source': 'point_source',
            'type': 'circle',
            'paint': {
                'circle-radius': 10,
                'circle-color': '#007cbf'
            }
        });
    }
})

</script>

</body>
</html>
...