使用方位角旋转Google Maps图标

时间:2019-05-27 12:02:55

标签: javascript google-maps

我有这张地图https://jsfiddle.net/e80zkacn/,上面有汽车图标。在0度时,汽车的图标朝北,但在我将其旋转270度时,却指向其前进的位置。我希望汽车始终使用方位角面向正确的位置。

我正在使用的公式是atan2,如此处https://www.igismap.com/formula-to-find-bearing-or-heading-angle-between-two-points-latitude-longitude/

所述

这是代码

    var map, marker;
var startPos = [42.42679066670903, -83.29210638999939];
var speed = 50; // km/h
var bearing = 2.6;

var symbol = {  
    path: "M62.1,36.5c-0.9-1.2-3.6-1.5-3.6-1.5c0.1-3.5,0.5-6.9,0.7-8.2c1.9-7.3-1.7-11.8-1.7-11.8c-4.8-4.8-9.1-5-12.5-5   c-3.4,0-7.8,0.3-12.5,5c0,0-3.6,4.5-1.7,11.8c0.2,1.2,0.5,4.6,0.7,8.2c0,0-2.7,0.3-3.6,1.5c-0.9,1.2-0.9,1.9,0,1.9   c0.9,0,2.9-2.3,3.6-2.3V35c0,1,0.1,2,0.1,3c0,4.4,0,33.7,0,33.7s-0.3,6.1,5,7.8c1.2,0,4.6,0.4,8.4,0.5c3.8-0.1,7.3-0.5,8.4-0.5   c5.3-1.7,5-7.8,5-7.8s0-29.3,0-33.7c0-1,0-2,0.1-3v1.2c0.7,0,2.7,2.3,3.6,2.3C63,38.5,63,37.7,62.1,36.5z M34.7,66.5   c-0.3,3.3-2.3,4.1-2.3,4.1V37.4c0.8,1.2,2.3,6.8,2.3,6.8S34.9,63.2,34.7,66.5z M54.8,75.2c0,0-4.2,2.3-9.8,2.2   c-5.6,0.1-9.8-2.2-9.8-2.2v-2.8c4.9,2.2,9.8,2.2,9.8,2.2s4.9,0,9.8-2.2V75.2z M35.2,41.1l-1.7-10.2c0,0,4.5-3.2,11.5-3.2   s11.5,3.2,11.5,3.2l-1.7,10.2C51.4,39.2,38.6,39.2,35.2,41.1z M57.7,70.6c0,0-2.1-0.8-2.3-4.1c-0.3-3.3,0-22.4,0-22.4   s1.5-5.6,2.3-6.8V70.6z",
    fillColor: '#FF0000',
    fillOpacity: .5,
    anchor: new google.maps.Point(0, 0),
    strokeWeight: 1,
    scale: .5,
    rotation: bearing  
}

var delay = 100;
// If you set the delay below 1000ms and you go to another tab,
// the setTimeout function will wait to be the active tab again
// before running the code.
// See documentation :
// https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Inactive_tabs

function animateMarker(marker, coords, km_h)
{
    var target = 0;
    var km_h = km_h || 50;
    coords.push([startPos[0], startPos[1]]);

    function goToPoint()
    {

    function radians_to_degrees(radians)
{
  var pi = Math.PI;
  return radians * (180/pi);
}

        var lat = marker.position.lat();
        var lng = marker.position.lng();
        var step = (km_h * 1000 * delay) / 3600000; // in meters

        var dest = new google.maps.LatLng(
        coords[target][0], coords[target][1]);

        var distance =
        google.maps.geometry.spherical.computeDistanceBetween(
        dest, marker.position); // in meters

        var numStep = distance / step;
        var i = 0;
        var deltaLat = (coords[target][0] - lat) / numStep;
        var deltaLng = (coords[target][1] - lng) / numStep;

        function the_bearing(){
        //console.log('x', lat);
        //console.log('y', lng);
        let bear = Math.atan2(lat, lng);

       var brng = radians_to_degrees(bear);
       brng = (brng + 360) % 360;

        console.log('angle is ', brng);
        }   
        the_bearing();


        function moveMarker()
        {
            lat += deltaLat;
            lng += deltaLng;
            i += step;

            if (i < distance)
            {
                marker.setPosition(new google.maps.LatLng(lat, lng));
                setTimeout(moveMarker, delay);
            }
            else
            {   marker.setPosition(dest);
                target++;
                if (target == coords.length){ target = 0; }

                setTimeout(goToPoint, delay);
            }
        }
        moveMarker();   

    }
    goToPoint();
}

function initialize()
{
    var myOptions = {
        zoom: 16,
        center: new google.maps.LatLng(42.425175091823974, -83.2943058013916),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map"), myOptions);
    var icon = symbol;

    marker = new google.maps.Marker({
        position: new google.maps.LatLng(startPos[0], startPos[1]),
        map: map,
        icon: icon
    });

    google.maps.event.addListenerOnce(map, 'idle', function()
    {
        animateMarker(marker, [
            // The coordinates of each point you want the marker to go to.
            // You don't need to specify the starting position again.
            [42.42666395645802, -83.29694509506226],
            [42.42300508749226, -83.29679489135742],
            [42.42304468678425, -83.29434871673584],
            [42.424882066428424, -83.2944130897522],
            [42.42495334300206, -83.29203128814697]
        ], speed);
    });
}

initialize();

目前,atan2的结果正在转换为度数,我对此表示怀疑。我如何才能使svg图标始终面对其前进的方向,并且有一种可靠的方法可以使svg图标始终朝着其前进的方向看?。

1 个答案:

答案 0 :(得分:3)

geometry library for Google Maps' JavaScript API提供了一种称为google.maps.geometry.spherical.computeHeading(p1, p2)的有用方法,可以精确计算从point1point2的标题。

我可以随意修改您的代码。这是jsfiddle

请注意正确地锚定您的图标,该锚定位于(0, 0)处,这会使汽车驶离道路。我试图对其进行更改,以使其看起来更自然。

<!Doctype html>
<meta charset="UTF-8">
<head>
<style>
#map {
    width: 600px;
    height: 400px;
}
</style>

</head>
<body>
<div id="map"></div>
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBx6MYRybsImp6aSn4xPphPFlGF3IaOr88&libraries=geometry"></script>
<script type="text/javascript">
var map, marker;
var startPos = [42.42679066670903, -83.29210638999939];
var speed = 270; // km/h
var bearing = 270;

var symbol = {  
    path: "M62.1,36.5c-0.9-1.2-3.6-1.5-3.6-1.5c0.1-3.5,0.5-6.9,0.7-8.2c1.9-7.3-1.7-11.8-1.7-11.8c-4.8-4.8-9.1-5-12.5-5   c-3.4,0-7.8,0.3-12.5,5c0,0-3.6,4.5-1.7,11.8c0.2,1.2,0.5,4.6,0.7,8.2c0,0-2.7,0.3-3.6,1.5c-0.9,1.2-0.9,1.9,0,1.9   c0.9,0,2.9-2.3,3.6-2.3V35c0,1,0.1,2,0.1,3c0,4.4,0,33.7,0,33.7s-0.3,6.1,5,7.8c1.2,0,4.6,0.4,8.4,0.5c3.8-0.1,7.3-0.5,8.4-0.5   c5.3-1.7,5-7.8,5-7.8s0-29.3,0-33.7c0-1,0-2,0.1-3v1.2c0.7,0,2.7,2.3,3.6,2.3C63,38.5,63,37.7,62.1,36.5z M34.7,66.5   c-0.3,3.3-2.3,4.1-2.3,4.1V37.4c0.8,1.2,2.3,6.8,2.3,6.8S34.9,63.2,34.7,66.5z M54.8,75.2c0,0-4.2,2.3-9.8,2.2   c-5.6,0.1-9.8-2.2-9.8-2.2v-2.8c4.9,2.2,9.8,2.2,9.8,2.2s4.9,0,9.8-2.2V75.2z M35.2,41.1l-1.7-10.2c0,0,4.5-3.2,11.5-3.2   s11.5,3.2,11.5,3.2l-1.7,10.2C51.4,39.2,38.6,39.2,35.2,41.1z M57.7,70.6c0,0-2.1-0.8-2.3-4.1c-0.3-3.3,0-22.4,0-22.4   s1.5-5.6,2.3-6.8V70.6z",
    fillColor: '#FF0000',
    fillOpacity: .5,
    anchor: new google.maps.Point(45, 45),
    strokeWeight: 1,
    scale: .5,
    rotation: bearing  
}

var delay = 100;
// If you set the delay below 1000ms and you go to another tab,
// the setTimeout function will wait to be the active tab again
// before running the code.
// See documentation :
// https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Inactive_tabs

function animateMarker(marker, coords, km_h)
{
    var target = 0;
    var km_h = km_h || 50;
    coords.push([startPos[0], startPos[1]]);
    console.log(coords);

    function goToPoint()
    {
        var lastPosn = marker.getPosition();
        var lat = marker.position.lat();
        var lng = marker.position.lng();
        var step = (km_h * 1000 * delay) / 3600000; // in meters

        var start = new google.maps.LatLng(startPos[0], startPos[1]);
        var dest = new google.maps.LatLng(coords[target][0], coords[target][1]);

        var distance = google.maps.geometry.spherical.computeDistanceBetween(dest, marker.position); // in meters

        var numStep = distance / step;
        var i = 0;
        var deltaLat = (coords[target][0] - lat) / numStep;
        var deltaLng = (coords[target][1] - lng) / numStep;

        function moveMarker()
        {
            lat += deltaLat;
            lng += deltaLng;
            i += step;

            if (i < distance)
            {
                var p = new google.maps.LatLng(lat, lng);
                marker.setPosition(p);

                var heading = google.maps.geometry.spherical.computeHeading(lastPosn, p);
                symbol.rotation = heading;
                marker.setIcon(symbol);

                setTimeout(moveMarker, delay);
            }
            else
            {   
                marker.setPosition(dest);

                var heading = google.maps.geometry.spherical.computeHeading(lastPosn, dest);
                symbol.rotation = heading;
                marker.setIcon(symbol);

                target++;
                if (target == coords.length){ target = 0; }

                setTimeout(goToPoint, delay);
            }
        }

        moveMarker();
    }
    goToPoint();
}

function initialize()
{
    var myOptions = {
        zoom: 16,
        center: new google.maps.LatLng(42.425175091823974, -83.2943058013916),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map"), myOptions);

    marker = new google.maps.Marker({
        position: new google.maps.LatLng(startPos[0], startPos[1]),
        map: map,
        icon: symbol
    });

    google.maps.event.addListenerOnce(map, 'idle', function()
    {
        animateMarker(marker, [
            // The coordinates of each point you want the marker to go to.
            // You don't need to specify the starting position again.
            [42.42666395645802, -83.29694509506226],
            [42.42300508749226, -83.29679489135742],
            [42.42304468678425, -83.29434871673584],
            [42.424882066428424, -83.2944130897522],
            [42.42495334300206, -83.29203128814697]
        ], speed);
    });
}

initialize();
</script>
</body>
</html>

我认为代码的某些部分可以使用API​​中的其他方法,例如计算deltaLatdeltaLng,但我不确定。

我也不确定moveMarker()方法是否必须在两种情况下进行拆分,但是我可能是错的。