【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏

【成图】

【代码】

复制代码
<!DOCTYPE html>
<html lang="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<head>
     <title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title>
     <style type="text/css">
     .centerlize{
        margin:0 auto;
        width:1200px;
     }
     </style>
     </head>

     <body οnlοad="init();">
        <div class="centerlize">
            <canvas id="myCanvas" width="12px" height="12px" style="border:1px dotted black;">
                如果看到这段文字说您的浏览器尚不支持HTML5 Canvas,请更换浏览器再试.
            </canvas>
        </div>
     </body>
</html>
<script type="text/javascript">
<!--
/*****************************************************************
* 将全体代码(从<!DOCTYPE到script>)拷贝下来,粘贴到文本编辑器中,
* 另存为.html文件,再用chrome浏览器打开,就能看到实现效果。
******************************************************************/

// canvas的绘图环境
var ctx;

// 高宽
const WIDTH=512;
const HEIGHT=512;

// 舞台对象
var stage;

// 暂停标志
var paused=false;

//-------------------------------
// 初始化
//-------------------------------
function init(){
    // 获得canvas对象
    var canvas=document.getElementById('myCanvas');  

    // 设置点击鼠标暂停
    canvas.οnclick=function(e){
        paused=! paused;
    }

    // 设置高宽
    canvas.width=WIDTH;
    canvas.height=HEIGHT;

    // 初始化canvas的绘图环境
    ctx=canvas.getContext('2d');  
    ctx.translate(WIDTH/2,HEIGHT/2);// 原点平移

    // 准备
    stage=new Stage();    
    stage.init();

    // 开幕
    animate();
}

// 播放动画
function animate(){    
    stage.update();    
    stage.paintBg(ctx);
    stage.paintFg(ctx);     

    // 循环
    if(true){
        //sleep(100);
        window.requestAnimationFrame(animate);   
    }
}

// 舞台类
function Stage(){
    this.theta=0;

    // 初始化
    this.init=function(){
        
    }

    // 更新
    this.update=function(){ 
        if(!paused){
            this.theta+=0.02;
        }
    }

    // 画背景
    this.paintBg=function(ctx){
        ctx.clearRect(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT);// 清屏    
    }

    // 画前景
    this.paintFg=function(ctx){
        // 底色
        ctx.save();
        ctx.fillStyle = "white";
        ctx.fillRect(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT);
        ctx.restore();

        const R=210;// 基准尺寸
                
        // 第1圈
        ctx.save();
        var r=R*1.00;
        drawSolidCircle(ctx,0,0,r,"rgb(191,128,53)");
        ctx.restore();

        // 第2圈
        ctx.save();
        var r=R*0.995;
        var gnt=ctx.createLinearGradient(0,-r,0,r);
        gnt.addColorStop(0,"rgb(241,215,94)");
        gnt.addColorStop(0.5,"rgb(207,157,42)");
        gnt.addColorStop(1,"rgb(163,107,39)");
        drawSolidCircle(ctx,0,0,r,gnt);
        ctx.restore();

        // 第3圈
        ctx.save();
        var r=R*0.975;
        var gnt=ctx.createLinearGradient(0,-r,0,r);
        gnt.addColorStop(0,"rgb(165,108,32)");
        gnt.addColorStop(0.5,"rgb(212,158,44)");
        gnt.addColorStop(1,"rgb(247,215,100)");
        drawSolidCircle(ctx,0,0,r,gnt);
        ctx.restore();

        // 第4圈
        ctx.save();
        var r=R*0.955;
        var gnt=ctx.createLinearGradient(0,-r,0,r);
        gnt.addColorStop(0,"rgb(176,112,37)");
        gnt.addColorStop(0.5,"rgb(173,144,59)");
        gnt.addColorStop(1,"rgb(185,183,109)");
        drawSolidCircle(ctx,0,0,r,gnt);
        ctx.restore();

        // 第5圈 雷达屏开始
        ctx.save();
        var r=R*0.95;
        drawSolidCircle(ctx,0,0,r,"rgb(0,14,27)");
        ctx.restore();

        // 角度
        ctx.save();
        var r=R*0.90;
        var N=36;
        for(var i=0;i<N;i++){
            var theta=Math.PI*2/N*i-Math.PI/2;

            var pt=createPt(r*Math.cos(theta),r*Math.sin(theta));

            ctx.font=r/22+"px Microsoft YaHei UI";
            ctx.textAlign="center";
            ctx.textBaseLine="Middle";
            ctx.fillStyle="rgb(43,185,187)";
            ctx.fillText((i*10).toString().padStart(3, '0'),pt.x,pt.y+r/45);
            
        }
        ctx.restore();

        // 大圆
        ctx.save();
        var r=R*0.85;
        ctx.strokeStyle="rgb(43,185,187)";
        ctx.lineWidth=R/105;
        ctx.beginPath();
        ctx.arc(0,0,r,0,Math.PI*2,false);
        ctx.closePath();
        ctx.stroke();
        ctx.restore();

        // 刻度
        ctx.save();
        var r=R*0.85;
        var N=36;
        for(var i=0;i<N;i++){
            var theta=Math.PI*2/N*i;            

            var rad1=r/20*20;
            var rad2=r/20*18;    
            var rad3=r/20*19;
            var pt=createPt(rad1*Math.cos(theta),rad1*Math.sin(theta));
            var pt2=createPt(rad2*Math.cos(theta),rad2*Math.sin(theta));
            if(i%2==0){
                pt2=createPt(rad3*Math.cos(theta),rad3*Math.sin(theta));
            }

            ctx.lineWidth=R/210;
            ctx.strokeStyle="rgb(43,185,187)";
            ctx.beginPath();
            ctx.moveTo(pt.x,pt.y);
            ctx.lineTo(pt2.x,pt2.y);
            ctx.stroke();                
        }
        ctx.restore();

        // 纵横线
        ctx.save();
        var r=R*0.85;        
        
        ctx.arc(0,0,r,0,Math.PI*2,false);
        ctx.clip();// 切图圆

        ctx.strokeStyle="rgb(43,185,187)";
        ctx.lineWidth=R/420;

        var N=12;
        var PART=2*r/N;
        
        for(var i=0;i<N;i++){ // 竖线
            var a=createPt(-r+i*PART,-r);
            var b=createPt(-r+i*PART,+r);

            ctx.beginPath();
            ctx.moveTo(a.x,a.y);
            ctx.lineTo(b.x,b.y);
            ctx.stroke();
        }

        for(var i=0;i<N;i++){ // 横线
            var a=createPt(-r,-r+i*PART);
            var b=createPt(+r,-r+i*PART);

            ctx.beginPath();
            ctx.moveTo(a.x,a.y);
            ctx.lineTo(b.x,b.y);
            ctx.stroke();
        }
        ctx.restore();

        // 五个同心圆
        ctx.save();
        var r=R*0.85;
        ctx.strokeStyle="rgb(43,185,187)";
        ctx.lineWidth=R/420;

        for(var i=1;i<=5;i++){
            var radius=r/5*i;
            ctx.beginPath();
            ctx.arc(0,0,radius,0,Math.PI*2,false);
            ctx.closePath();
            ctx.stroke();
        }
        ctx.restore();

        // 扫描扇形
        ctx.save();
        const ANGLE=Math.PI/3*1;
        var r=R*0.85;
        var a=createPt(r*Math.cos(this.theta),r*Math.sin(this.theta));
        var b=createPt(r*Math.cos(this.theta+ANGLE),r*Math.sin(this.theta+ANGLE));
        var c=createPt(a.x*Math.cos(ANGLE),a.y*Math.cos(ANGLE));

        ctx.strokeStyle="rgb(43,185,187)";// 牵引棒
        ctx.lineWidth=R/210;
        ctx.beginPath();
        ctx.moveTo(0,0);
        ctx.lineTo(b.x,b.y);
        ctx.stroke();

        var gnt=ctx.createLinearGradient(b.x,b.y,c.x,c.y);// 线性渐变色
        gnt.addColorStop(0,"rgba(255,255,255,0.6)");
        gnt.addColorStop(0.5,"rgba(255,255,255,0.4)");
        gnt.addColorStop(1,"rgba(255,255,255,0.2)");
        ctx.fillStyle=gnt;
        ctx.beginPath();
        ctx.moveTo(0,0);
        ctx.lineTo(a.x,a.y);
        ctx.arc(0,0,r,this.theta,this.theta+ANGLE,false);
        ctx.closePath();
        ctx.fill();

        ctx.restore();

        // 三个模拟目标点
        ctx.save();
        var r=R*0.98;
        var startAngle=((this.theta/Math.PI*180)%360)/180*Math.PI;
        var endAngle=(((this.theta+ANGLE)/Math.PI*180)%360)/180*Math.PI;

        var l=r*0.55;
        var angle=Math.PI*0.33;
        var a=createPt(l*Math.cos(angle),l*Math.sin(angle));
        if(startAngle<angle && angle<endAngle){
            drawSolidCircle(ctx,a.x,a.y,r*0.02,"white");
        }else{            
            var gnt=ctx.createRadialGradient(a.x,a.y,0,a.x,a.y,r*0.02);// 辐射渐变
            gnt.addColorStop(0,"rgba(190,199,190,0.8)");
            gnt.addColorStop(0.5,"rgba(190,199,190,0.4");
            gnt.addColorStop(1,"rgba(190,199,190,0.1");
            drawSolidCircle(ctx,a.x,a.y,r*0.02,gnt);
        }

        l=r*0.75;
        angle=Math.PI*0.8;
        var a=createPt(l*Math.cos(angle),l*Math.sin(angle));
        if(startAngle<angle && angle<endAngle){
            drawSolidCircle(ctx,a.x,a.y,r*0.02,"white");
        }else{            
            var gnt=ctx.createRadialGradient(a.x,a.y,0,a.x,a.y,r*0.02);// 辐射渐变
            gnt.addColorStop(0,"rgba(190,199,190,0.8)");
            gnt.addColorStop(0.5,"rgba(190,199,190,0.4");
            gnt.addColorStop(1,"rgba(190,199,190,0.1");
            drawSolidCircle(ctx,a.x,a.y,r*0.02,gnt);
        }

        var l=r*0.65;
        var angle=Math.PI*1.4;
        var a=createPt(l*Math.cos(angle),l*Math.sin(angle));
        if(startAngle<angle && angle<endAngle){
            drawSolidCircle(ctx,a.x,a.y,r*0.02,"white");
        }else{            
            var gnt=ctx.createRadialGradient(a.x,a.y,0,a.x,a.y,r*0.02);// 辐射渐变
            gnt.addColorStop(0,"rgba(190,199,190,0.8)");
            gnt.addColorStop(0.5,"rgba(190,199,190,0.4");
            gnt.addColorStop(1,"rgba(190,199,190,0.1");
            drawSolidCircle(ctx,a.x,a.y,r*0.02,gnt);
        }

        ctx.restore();

        writeText(ctx,WIDTH/2-30,HEIGHT/2-5,"逆火制图","8px consolas","lightgrey");// 版权
    }
}

/*----------------------------------------------------------
函数:用于绘制实心圆,用途是标记点以辅助作图
ctx:绘图上下文
x:矩形中心横坐标
y:矩形中心纵坐标
r:圆半径
color:填充圆的颜色
----------------------------------------------------------*/
function drawSolidCircle(ctx,x,y,r,color){
    ctx.fillStyle=color;
    ctx.beginPath();
    ctx.arc(x,y,r,0,Math.PI*2,false);
    ctx.closePath();
    ctx.fill();
}

/*----------------------------------------------------------
函数:创建一个二维坐标点
x:横坐标
y:纵坐标
Pt即Point
----------------------------------------------------------*/
function createPt(x,y){
    var retval={};
    retval.x=x;
    retval.y=y;
    return retval;
}

/*----------------------------------------------------------
函数:延时若干毫秒
milliseconds:毫秒数
----------------------------------------------------------*/
function sleep(milliSeconds) {
    const date = Date.now();
    let currDate = null;
    while (currDate - date < milliSeconds) {
        currDate = Date.now();
    } 
}

/*----------------------------------------------------------
函数:书写文字
ctx:绘图上下文
x:横坐标
y:纵坐标
text:文字
font:字体
color:颜色
----------------------------------------------------------*/
function writeText(ctx,x,y,text,font,color){
    ctx.save();
    ctx.textBaseline="bottom";
    ctx.textAlign="center";
    ctx.font = font;
    ctx.fillStyle=color;
    ctx.fillText(text,x,y);
    ctx.restore();
}

/*-------------------------------------------------------------
人不自信的最根本原因是什么?
对世界:没有认识到,这个世界就是个巨大的草台班子
对自己:没有认识到,除了极个别天才,其他人之间差别没想象的那麽大
比你拉跨,但比你赚钱多的人有,比你牛,但没你赚钱多的人也有
放轻松,才能展示自己最好的一面。
负担不要太重,也不要怕出丑,
其实人生,无非就是:你笑笑别人,别人笑笑你。
--------------------------------------------------------------*/
//-->
</script>

END

相关推荐
SunFlower91417 小时前
v3通过pdfjs-dist插件渲染后端返回的pdf文件流,并实现缩放、下一页
前端·svg·canvas·pdfjs-dist
Marshall357210 天前
Canvas 和 SVG 的高级使用与性能优化
前端·svg·canvas
webmote12 天前
做一个FabricJS.cc的中文文档网站——面向markdown编程
canvas·fabric·使用手册·中文·fabricjs
小黄人软件18 天前
【AI协作】让所有用电脑的场景都能在ChatGPT里完成。Canvas :新一代可视化交互,让AI易用易得
人工智能·chatgpt·canvas
柳晓黑胡椒22 天前
cesiusm实现 多图例展示+点聚合(base64图标)
css3·canvas·base64·cesium·animation
余生H1 个月前
即时可玩web小游戏(二):打砖块(支持移动端版) - 集成InsCode快来阅读并即时体验吧~
前端·javascript·inscode·canvas·h5游戏
普兰店拉马努金1 个月前
【Canvas与图标】牛皮纸文件袋图标
canvas·图标·文件袋·牛皮纸
德育处主任1 个月前
前端啊,拿Lottie炫个动画吧
前端·svg·canvas
GDAL1 个月前
深入剖析Canvas的getBoundingClientRect:精准定位与交互事件实现
canvas