Ruiily 2019-05-19 21:01 采纳率: 0%
浏览 719

如何用JavaScript实现方位角计算并且调用指针指示角度?


```<!DOCTYPE html>
<head>

    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta content="always" name="referrer">
    <meta name="theme-color" content="#2932e1">
    <title>RCP For A320NG</title>
</head>
<body>

<style>
.shu    {
         width: 2px; 
         font-size: 15px; 
         word-wrap: break-word;
         }
@font-face{
      font-family: digital-display;
      src: url('digital-display.ttf'),
      url('digital-display.eot'); /* IE9+ */
}
.Digits{
    position:absolute;
    top:120px;left:10px;
    height:60px;width:230px;
    line-height:60px;
    color:white;
    font-size:70px;font-family:digital-display;
    display:block; float:left; 
    text-align:right;
    }
.to_top {
    width: 0;
    height: 0;
    border-bottom: 30px solid white;
    border-left: 20px solid transparent;
    border-right: 20px solid transparent;
        }
.top{
    width: 0;
    height: 0;
    border-bottom: 30px solid white;
    border-left: 20px solid transparent ;
    border-right: 20px solid transparent ;

}

</style>

<div id="DME1" class = "Digits" style="">1.300</div>
<div id="DME2" class = "Digits" style="left:260px;">----</div> 
 <div id="asd"style="position: absolute; top:600px;left:200px;font-family: Microsoft YaHei;letter-spacing:5px;color:white;">ADF</div>
<div id="asd1"style="position: absolute; top:600px;left:350px;font-family: Microsoft YaHei;letter-spacing:5px;color:white;">ADF</div> 
<div id="asd2"class="shu" style="position: absolute; left:80px;top:470px;font-family: Microsoft YaHei;color:white;">VOR</div>
<div id="asd3"class="shu" style="position: absolute; left:480px;top:470px;font-family: Microsoft YaHei;color:white;">VOR</div>
<div id="mat"class="to_top" style="position: absolute; left:60px;top:570px;color:white;"></div>
<div id="mat2"style="position: absolute; width:10px;height:10px;border:1px solid white;left:75px;top:600px;background:white;"></div>
<div id="mat3"style="position: absolute; width:10px;height:10px;border:1px solid white;left:75px;top:615px;background:white;"></div>
<div id="mat4"style="position: absolute; width:10px;height:10px;border:1px solid white;left:75px;top:630px;background:white;"></div>



<div id="ExchangeBtn" class="button" style="position:absolute; left:470px;top:600px;font-size:90px;font-weight:bold;font-family: Microsoft YaHei;line-height:15px;color:white;">&#8679;</div> 

<canvas id="solar" style="border:0px solid;left:10px;top:10px;position:absolute;z-index:-1;width:560px;height:670px;scale:0.5;"></canvas>
<div id="Message" ></div>
<div id="Message2" ></div>
</body>

<script>
init();
let pi = Math.PI;
let DialCenterX = 275;
let DialCenterY = 400;
let DialRadius = 180;
let CompassHeading = 0;
let Latitude=0;
let Longitude=0;
let DME1_lat= 39.10960;
let DME1_long= 117.35343;
let DME1Distance = 0;

let hand1=30; //VOR方位角
let hand2=0;

let gap_dial_hand = 60;
let hand_length = DialRadius - gap_dial_hand;

window.addEventListener("deviceorientation", findNorth);
var Message =document.getElementById("Message");

var browser={
    versions:function(){
        var u = navigator.userAgent, app = navigator.appVersion;
        return {
            trident: u.indexOf('Trident') > -1, //IE内核
            presto: u.indexOf('Presto') > -1, //opera内核
            webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核
            mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
            ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
            android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, //android终端
            iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
            iPad: u.indexOf('iPad') > -1, //是否iPad
            webApp: u.indexOf('Safari') == -1, //是否web应该程序,没有头部与底部
            weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增)
            qq: u.match(/\sQQ/i) == " qq" //是否QQ
        };
    }(),
    language:(navigator.browserLanguage || navigator.language).toLowerCase()
}


function draw(ctx,DialDeg,HandDeg1,HandDeg2){
        //drawDial(ctx,DialDeg); //绘制表盘
        //drawAllHands(ctx,HandDeg1,HandDeg2); //绘制时分秒针

    requestAnimationFrame(function step(){
        getLocation();
        DME1Distance = getDisance(Latitude, Longitude, DME1_lat, DME1_long);
        if(DME1Distance>722094) DME1Distance="----";
        document.getElementById("DME1").innerHTML = DME1Distance;
        drawDial(ctx,CompassHeading); //绘制表盘
        drawAllHands(ctx,hand1,hand2); //绘制时分秒针
        requestAnimationFrame(step);
    });
}


function toRad(d) {  return d * Math.PI / 180; }
function getDisance(lat1, lng1, lat2, lng2) { //lat为纬度, lng为经度, 一定不要弄错
    var dis = 0;
    var radLat1 = toRad(lat1);
    var radLat2 = toRad(lat2);
    var deltaLat = radLat1 - radLat2;
    var deltaLng = toRad(lng1) - toRad(lng2);
    var dis = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(deltaLat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(deltaLng / 2), 2)));
    dis = dis * 6378137;
    dis = dis ;///1852 ;//转为海里
    return dis.toFixed(1);
} 
function getLocation()
{
      if (navigator.geolocation)
        {
            navigator.geolocation.getCurrentPosition(showPosition);
        }
      else{
        Message.innerHTML="Geolocation is not supported by this browser.";
        }
}
function showPosition(position)  
{
      Message.innerHTML="Latitude: " + position.coords.latitude +  "<br />Longitude: " + position.coords.longitude +"<br/>accuracy:"+ position.coords.accuracy;
      Latitude = position.coords.latitude; Longitude = position.coords.longitude;
}



function findNorth(evt) {

    if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
        CompassHeading = 360-evt.webkitCompassHeading.toFixed(0);
        //window.location.href ="iPhone.html";
    } else if (/(Android)/i.test(navigator.userAgent)) {
        //alert(navigator.userAgent); 
        CompassHeading = evt.alpha -90;
        document.getElementById("Message2").innerHTML = "您的手机需要校准指南针,请将手机指向正北后刷新页面。";
    } else {        
    }
}

    function init(){
        let canvas = document.querySelector("#solar");
        canvas.width = 560;
        canvas.height = 670;
        let ctx = canvas.getContext("2d");


        drawOutline(ctx);
        //strokeRoundRect(ctx, 10, 10, 100, 50, 10);

        fillRoundRect(ctx, 40, 95, 216, 124, 30, 'rgba(99,116,122,1)');
        fillRoundRect(ctx, 50, 105, 192, 68, 15, 'rgba(0,0,0,1)');
        fillRoundRect(ctx, 295, 95, 216, 124, 30, 'rgba(99,116,122,1)');
        fillRoundRect(ctx, 305, 105, 192, 68, 15, 'rgba(0,0,0,1)');
        //fillRoundRect(ctx, 50, 50, 450, 600, 20, 'rgba(0,0,0,1)');
        draw(ctx,30,30,60); 
        ctx.font = '20px "微软雅黑"';
        ctx.fillStyle = "white";
        ctx.fillText("DME-1", 110, 200);
        ctx.font = '20px "微软雅黑"';
        ctx.fillStyle = "white";
        ctx.fillText("DME-2", 370, 200);
    }




    /*绘制时分秒针*/
    function drawAllHands(ctx,HandDeg1,HandDeg2){
        let time = new Date();

        let s = time.getSeconds();
        let m = time.getMinutes();
        let h = time.getHours();

        let pi = Math.PI;
        let secondAngle = HandDeg1;//pi / 180 * 6 * s;  //计算出来s针的弧度
        let minuteAngle = pi / 180 * HandDeg1;  //计算出来分针的弧度
        let hourAngle = pi / 180 *HandDeg2;//pi / 180 * 30 * h + minuteAngle / 12;  //计算出来时针的弧度

        //

        drawHand2(hand2 + CompassHeading, hand_length, 2, "white", ctx);  //绘制时针,(角度,针长,粗细,颜色,canvas)
        drawHand(hand1 + CompassHeading, hand_length, 2, "white", ctx);  //绘制分针
        //drawHand(secondAngle, 150, 2, "blue", ctx);  //绘制秒针
    }
    /*绘制时针、或分针、或秒针
     * 参数1:要绘制的针的角度
     * 参数2:要绘制的针的长度
     * 参数3:要绘制的针的宽度
     * 参数4:要绘制的针的颜色
     * 参数4:ctx
     * */
    function drawHand(angle, len, width, color, ctx){
        ctx.save();
        ctx.translate(DialCenterX, DialCenterY); //把坐标轴的远点平移到原来的中心
        ctx.rotate(angle*pi/180 + pi/2);  //旋转坐标轴。 x轴就是针的角度,rad
        ctx.beginPath();
        ctx.moveTo(-DialRadius + gap_dial_hand, 0);
        //ctx.lineTo(len, 0);  // 沿着x轴绘制针
        ctx.font="18px microsoft yahei";
        ctx.fillStyle="white";
        var x = 4-DialRadius + gap_dial_hand; //指针起点x
        ctx.fillText("◀",x,6);
        for(i=x+5;i<len;){
            ctx.moveTo(i, 0);
            ctx.lineTo(i+10, 0);
            i = i+20;
        }
        ctx.lineWidth = width;
        ctx.strokeStyle = color;
        ctx.lineCap = "round";
        ctx.stroke();
        ctx.closePath();
        ctx.restore();
    }
    function drawHand2(angle, len, width, color, ctx){
        ctx.save();
        ctx.translate(DialCenterX, DialCenterY); //把坐标轴的远点平移到原来的中心
        ctx.rotate(angle*pi/180 +pi/2);  //旋转坐标轴。 x轴就是针的角度
        ctx.beginPath();
        ctx.moveTo(-DialRadius + gap_dial_hand, 0);
        //ctx.lineTo(len, 0);  // 沿着x轴绘制针
        ctx.font="30px microsoft yahei";
        ctx.fillStyle="white";

        var x = -DialRadius + gap_dial_hand;
        ctx.moveTo(x, 0);
        ctx.lineTo(x+20, 10);ctx.lineTo(x+20, 5);
        ctx.lineTo(len, 5);ctx.lineTo(len, -5);
        ctx.lineTo(x+20, -5);ctx.lineTo(x+20, -10);
        ctx.lineTo(x, 0);

        ctx.lineWidth = width;
        ctx.strokeStyle = color;
        ctx.lineCap = "round";
        ctx.stroke();
        ctx.closePath();
        ctx.restore();
    }







    /*绘制表盘*/
    function drawDial(ctx,DialDeg){
        let pi = Math.PI;

        //ctx.clearRect(0, 0, 600, 600); //清除所有内容
        ctx.save();     
            ctx.translate(DialCenterX, DialCenterY); //移动坐标原点到原来的中心     
            ctx.beginPath();
            ctx.arc(0, 0, DialRadius, 0, 2*pi); //绘制圆周
            //ctx.stroke();
            //context.clip();
            ctx.closePath();
            // 填充颜色  
            ctx.fillStyle = "#202020";  
            ctx.fill();

            for (let i = 0; i < 72; i++){//绘制刻度盘和数字
                ctx.save();
                ctx.rotate(pi/180*DialDeg + i * pi / 36);  //旋转坐标轴。修改第一个参数可以旋转表盘
                ctx.beginPath();
                ctx.moveTo(DialRadius-37, 0);
                if(i % 2 == 0){
                    ctx.lineTo(DialRadius-1, 0);
                }else{
                    ctx.lineTo(DialRadius-16, 0);
                }

                ctx.lineWidth = i % 5 ? 4 : 4;
                ctx.strokeStyle = i % 5 ? "white" : "white";
                ctx.stroke();
                ctx.closePath();

                if(i % 6 == 0){
                    ctx.lineWidth = 1;
                    ctx.font="24px microsoft yahei";
                    //ctx.strokeText(i/3,0,-150);
                    //填充
                    ctx.fillStyle="white";
                    if(i>9) ctx.fillText(i*0.5,-12,60-DialRadius);       //-150 
                    else    ctx.fillText(i*0.5,-6,60-DialRadius);
                }
                ctx.restore();
            }
            for (let i = 0; i < 8; i++){//绘制三角标
                ctx.save();
                ctx.rotate(pi/180*0 + i * pi / 4);  //旋转坐标轴。修改第一个参数可以旋转表盘     
                ctx.font="24px microsoft yahei";
                ctx.fillStyle="white";
                ctx.fillText("▼",-12,-1*DialRadius);
                ctx.restore();
            }
        ctx.restore();
    }
      VincentyConstants = {
            a: 6378137,
            b: 6356752.3142,
            f: 1/298.257223563
        }
        /**
        *Calculate destination point given start point lat/long (numeric degrees),
        * bearing (numeric degrees) & distance (in m).
        */
        function destinationVincenty(lonlat, brng, dist) {
            var u = this;
            var ct = u.VincentyConstants;
            var a = ct.a, b = ct.b, f = ct.f;

            var lon1 = lonlat.lon*1;  //乘一(*1)是为了确保经纬度的数据类型为number
            var lat1 = lonlat.lat*1;

            var s = dist;
            var alpha1 = u.rad(brng);
            var sinAlpha1 = Math.sin(alpha1);
            var cosAlpha1 = Math.cos(alpha1);

            var tanU1 = (1-f) * Math.tan(u.rad(lat1));
            var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
            var sigma1 = Math.atan2(tanU1, cosAlpha1);
            var sinAlpha = cosU1 * sinAlpha1;
            var cosSqAlpha = 1 - sinAlpha*sinAlpha;
            var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
            var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
            var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));

            var sigma = s / (b*A), sigmaP = 2*Math.PI;
            while (Math.abs(sigma-sigmaP) > 1e-12) {
                var cos2SigmaM = Math.cos(2*sigma1 + sigma);
                var sinSigma = Math.sin(sigma);
                var cosSigma = Math.cos(sigma);
                var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
                    B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
                sigmaP = sigma;
                sigma = s / (b*A) + deltaSigma;
            }

            var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
            var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
                (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
            var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
            var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
            var L = lambda - (1-C) * f * sinAlpha *
                (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));

            var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing


                    var lon_destina = lon1*1+u.deg(L);

                    //var num_lon_dest = lon_destina*1;

                    //var lon_destina = new Number;

            var lonlat_destination = {lon: lon_destina, lat: u.deg(lat2)};

            return lonlat_destination;
        }

         /**
         * 度换成弧度
         * @param  {Float} d  度
         * @return {[Float}   弧度
         */
        function rad(d)
        {
           return d * Math.PI / 180.0;
        }

        /**
         * 弧度换成度
         * @param  {Float} x 弧度
         * @return {Float}   度
         */
        function deg(x) {
            return x*180/Math.PI;
        }  
    function drawOutline (ctx){


        //开始路径
        ctx.beginPath();
        ctx.moveTo(70, 2);
        ctx.lineTo(472, 2);
        ctx.lineTo(550, 70);
        ctx.lineTo(550, 597);
        ctx.lineTo(472, 665);
        ctx.lineTo(70, 665);
        ctx.lineTo(2, 597);
        ctx.lineTo(2, 70);
        ctx.lineTo(70, 2);
        ctx.closePath();

        //路径闭合
        //if(strokeStyle) 
        {
            ctx.strokeStyle = "gray";
            ctx.lineWidth = 1;
            ctx.lineJoin = 'round';
            ctx.stroke();
        }
        //if(fillStyle) 
        {
            ctx.fillStyle = 'rgba(135,162,174,1)';
            ctx.fill();
        }
         ctx.restore();

         ctx.beginPath();
        ctx.moveTo(40, 84);
        ctx.lineTo(511, 84);
        ctx.lineTo(511, 510);
        ctx.lineTo(390, 642);
        ctx.lineTo(169, 642);
        ctx.lineTo(40, 510);
        ctx.lineTo(40, 84);
        ctx.closePath();
        {
            ctx.strokeStyle = "darkgray";
            ctx.lineWidth = 1;
            ctx.lineJoin = 'round';
            ctx.stroke();
        }
        //if(fillStyle) 
        {
            ctx.fillStyle = 'rgba(63,74,76,1)';
            ctx.fill();
            }




         }



/**该方法用来绘制一个有填充色的圆角矩形 
     *@param cxt:canvas的上下文环境 
     *@param x:左上角x轴坐标 
     *@param y:左上角y轴坐标 
     *@param width:矩形的宽度 
     *@param height:矩形的高度 
     *@param radius:圆的半径 
     *@param fillColor:填充颜色 
     **/
    function fillRoundRect(cxt, x, y, width, height, radius, /*optional*/ fillColor) {
        //圆的直径必然要小于矩形的宽高          
        if (2 * radius > width || 2 * radius > height) { return false; }

        cxt.save();
        cxt.translate(x, y);
        //绘制圆角矩形的各个边  
        drawRoundRectPath(cxt, width, height, radius);
        cxt.fillStyle = fillColor || "#000"; //若是给定了值就用给定的值否则给予默认值  
        cxt.fill();
        cxt.restore();
    }


    /**该方法用来绘制圆角矩形 
     *@param cxt:canvas的上下文环境 
     *@param x:左上角x轴坐标 
     *@param y:左上角y轴坐标 
     *@param width:矩形的宽度 
     *@param height:矩形的高度 
     *@param radius:圆的半径 
     *@param lineWidth:线条粗细 
     *@param strokeColor:线条颜色 
     **/
    function strokeRoundRect(cxt, x, y, width, height, radius, /*optional*/ lineWidth, /*optional*/ strokeColor) {
        //圆的直径必然要小于矩形的宽高          
        if (2 * radius > width || 2 * radius > height) { return false; }

        cxt.save();
        cxt.translate(x, y);
        //绘制圆角矩形的各个边  
        drawRoundRectPath(cxt, width, height, radius);
        cxt.lineWidth = lineWidth || 2; //若是给定了值就用给定的值否则给予默认值2  
        cxt.strokeStyle = strokeColor || "#000";
        cxt.stroke();
        cxt.restore();
    }

    function drawRoundRectPath(cxt, width, height, radius) {
        cxt.beginPath(0);
        //从右下角顺时针绘制,弧度从0到1/2PI  
        cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2); 
        //矩形下边线  
        cxt.lineTo(radius, height); 
        //左下角圆弧,弧度从1/2PI到PI  
        cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); 
        //矩形左边线  
        cxt.lineTo(0, radius); 
        //左上角圆弧,弧度从PI到3/2PI  
        cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2); 
        //上边线  
        cxt.lineTo(width - radius, 0); 
        //右上角圆弧  
        cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2); 
        //右边线  
        cxt.lineTo(width, height - radius);
        cxt.closePath();
    }


</script>
</html>
  • 写回答

1条回答 默认 最新

  • 雪梅零落 全栈领域优质创作者 2024-04-17 14:08
    关注

    方位角(Azimuth)计算通常涉及到地理坐标(纬度和经度)以及一个参考点。对于方位角,我们计算的是从一个点到另一个点的方向。

    计算两个地理坐标点之间的方位角:

    function calculateAzimuth(lat1, lon1, lat2, lon2) {
        var dLat = toRadians(lat2-lat1);
        var dLon = toRadians(lon2-lon1);
    
        var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * 
                Math.sin(dLon/2) * Math.sin(dLon/2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    
        var R = 6371; // 地球半径,单位:公里
        var d = R * c; // 两点之间的距离,单位:公里
    
        var bearing = toDegrees(Math.atan2(Math.sin(dLon) * Math.cos(toRadians(lat2)),
            Math.cos(toRadians(lat1)) * Math.sin(toRadians(lat2)) -
            Math.sin(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.cos(dLon)));
    
        if (bearing < 0) {
            bearing = 360 + bearing;
        }
    
        return bearing;
    }
    
    function toRadians(angle) {
        return angle * (Math.PI / 180);
    }
    
    function toDegrees(angle) {
        return angle * (180 / Math.PI);
    }
    

    这个函数首先使用toRadians函数将角度转换为弧度,然后计算两点之间的距离和方位角。最后,使用toDegrees函数将方位角从弧度转换回角度。

    接下来,你可以使用HTML和CSS来创建一个指针,并使用JavaScript来动态改变它的角度。以下是一个简单的例子:

    HTML:

    <div id="compass">
        <div id="pointer"></div>
    </div>
    

    CSS:

    #compass {
        width: 200px;
        height: 200px;
        border: 1px solid black;
        border-radius: 50%;
        position: relative;
        overflow: hidden;
    }
    
    #pointer {
        width: 50px;
        height: 2px;
        background-color: black;
        position: absolute;
        top: 50%;
        left: 50%;
        transform-origin: left;
        transform: rotate(0deg);
    }
    

    JavaScript:

    var lat1 = 40.7128; // 起始点的纬度
    var lon1 = -74.0060; // 起始点的经度
    var lat2 = 34.0522; // 目标点的纬度
    var lon2 = -118.2437; // 目标点的经度
    
    var bearing = calculateAzimuth(lat1, lon1, lat2, lon2);
    
    var pointer = document.getElementById('pointer');
    pointer.style.transform = 'rotate(' + bearing + 'deg)';
    
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料