【Canvas与艺术】雷达显示屏
【说明】
圆形的雷达显示屏由两种雷达探测的结果叠加而成。
整圆表示相控阵雷达,此种雷达探测角度广,侦测距离远,但不精确,得知目标的大致高度位置信息后便交由三坐标雷达做精确探测;
扇面表示三坐标雷达的侦测范围,该种雷达能精确测定目标的方位高度速度,但作用面窄;
实战中常把两种雷达配合起来用,如下图所示。
【图示】
【代码】
<!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head> <title>雷达显示屏</title> </head> <body onload="draw()"> <canvas id="myCanvus" width="512px" height="512px" style="border:0px dashed black;"> 出现文字表示您的浏览器不支持HTML5 </canvas> </body> </html> <script type="text/javascript"> <!-- /***************************************************************** * 将全体代码(从<!DOCTYPE到script>)拷贝下来,粘贴到文本编辑器中, * 另存为.html文件,再用chrome浏览器打开,就能看到实现效果。 ******************************************************************/ // 常量边长 const SideLength=512; // 绘图上下文 var context; // 雷达对象 var radar; function draw(){ var canvas=document.getElementById('myCanvus'); canvas.width=SideLength; canvas.height=SideLength; context=canvas.getContext('2d'); context.translate(SideLength/2,SideLength/2); radar=new Radar(SideLength/2); radar.init(); animate(); }; function animate(){ context.clearRect(-SideLength/2,-SideLength/2,SideLength,SideLength);// 清屏 radar.paintBg(context); radar.paintScale(context); radar.paintPointers(context); if(true){ window.requestAnimationFrame(animate); } } // 雷达类 function Radar(radius){ this.radius=radius; this.img; this.angle=0; // 横飞飞机的坐标 this.x1=-198; this.y1=100; // 纵飞飞机的坐标 this.x2=100; this.y2=-198; // 斜飞飞机的坐标 this.x3=-150; this.y3=-150; this.init=function(){ this.img=new Image(); this.img.src="67.copper.png"; } // 画背景 this.paintBg=function(ctx){ // 画雷达最外缘的金属护板 ctx.strokeStyle="white"; ctx.beginPath(); ctx.arc(0,0,this.radius,0,2*Math.PI,true); ctx.closePath(); ctx.stroke(); ctx.clip();// 用以上的圆去切割下面的图片 ctx.drawImage(this.img,0,0,400,400,-this.radius,-this.radius,2*this.radius,2*this.radius); // 画六颗螺丝 ctx.fillStyle="yellow"; var hourNumber = ["✪","❂","✪","❂","✪","❂"]; ctx.font = "18px Arial";//字体也有乘比例 字符串拼接 ctx.textAlign = "center"; ctx.textBaseline = "middle"; hourNumber.forEach(function (text, i) { var rad = 2 * Math.PI / 6 * i; var x = Math.cos(rad) * 239; var y = Math.sin(rad) * 239; // 螺丝外缘 ctx.strokeStyle="black"; ctx.lineWidth=3; ctx.beginPath(); ctx.arc(x,y,5,0,2*Math.PI,true); ctx.closePath(); ctx.stroke(); // 螺丝内文 ctx.fillText(text, x, y); }); // 画深绿色屏幕 ctx.fillStyle="#006000"; ctx.beginPath(); ctx.arc(0,0,224,0,2*Math.PI,true); ctx.closePath(); ctx.fill(); // 画屏幕与护板之间的橡胶条 ctx.strokeStyle="black"; ctx.lineWidth=5; ctx.beginPath(); ctx.arc(0,0,222,0,2*Math.PI,true); ctx.closePath(); ctx.stroke(); }; // 画刻度 this.paintScale=function(ctx){ // 画横轴 ctx.strokeStyle="#79FF79"; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(-219,0); ctx.lineTo(219,0); ctx.closePath(); ctx.stroke(); // 画纵轴 ctx.strokeStyle="#79FF79"; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(0,-219); ctx.lineTo(0,219); ctx.closePath(); ctx.stroke(); // 画500公里圆 ctx.strokeStyle="#79FF79"; ctx.lineWidth=1; ctx.beginPath(); ctx.arc(0,0,109.5,0,2*Math.PI,true); ctx.closePath(); ctx.stroke(); // 标两个500公里 ctx.fillStyle="white"; ctx.font = "8px Arial"; ctx.textAlign = "left"; ctx.textBaseline = "bottom"; ctx.fillText("500km", 109.5, 0); ctx.fillStyle="white"; ctx.font = "8px Arial"; ctx.textAlign = "right"; ctx.textBaseline = "bottom"; ctx.fillText("500km", -109.5, 0); // 标两个1000公里 ctx.fillStyle="white"; ctx.font = "8px Arial"; ctx.textAlign = "right"; ctx.textBaseline = "bottom"; ctx.fillText("1000km", 219, 0); ctx.fillStyle="white"; ctx.font = "8px Arial"; ctx.textAlign = "left"; ctx.textBaseline = "bottom"; ctx.fillText("1000km", -219, 0); }; // 画指针 this.paintPointers=function(ctx){ this.angle+=Math.PI/720; let x=Math.cos(this.angle)*219; let y=Math.sin(this.angle)*219; // 扫描棒 ctx.strokeStyle="#93FF93"; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(x,y); ctx.closePath(); ctx.stroke(); // 扫描扇形 ctx.fillStyle = 'rgba(0,200,0,0.3)'; ctx.beginPath(); ctx.moveTo(0, 0); ctx.arc(0, 0, 219, this.angle, this.angle-2*Math.PI/360*45,true); ctx.closePath(); ctx.fill(); // 横飞飞机 let anglePlane1=Math.atan2(this.y1, this.x1);// 算横飞飞机角度 if(anglePlane1>this.angle-2*Math.PI/360*45 && anglePlane1<this.angle){ ctx.fillStyle="#F0FFF0"; }else{ ctx.fillStyle="#53FF53"; } ctx.font = "10px Arial"; ctx.textAlign = "left"; ctx.textBaseline = "bottom"; ctx.fillText("✈", this.x1, this.y1); this.x1+=0.1; if(this.x1>198){ this.x1=-198; } // 纵飞飞机 let anglePlane2=Math.atan2(this.y2, this.x2);// 算纵飞飞机角度 if(anglePlane2>this.angle-2*Math.PI/360*45 && anglePlane2<this.angle){ ctx.fillStyle="#F0FFF0"; }else{ ctx.fillStyle="#53FF53"; } ctx.font = "10px Arial"; ctx.textAlign = "left"; ctx.textBaseline = "bottom"; ctx.save(); ctx.translate(this.x2, this.y2); ctx.rotate(Math.PI/2); ctx.fillText("✈", 0, 0); ctx.restore(); this.y2+=0.2; if(this.y2>192){ this.y2=-198; } // 斜飞飞机 let anglePlane3=Math.atan2(this.y3, this.x3);// 算斜飞飞机角度 if(anglePlane3>this.angle-2*Math.PI/360*45 && anglePlane3<this.angle){ ctx.fillStyle="#F0FFF0"; }else{ ctx.fillStyle="#53FF53"; } ctx.font = "10px Arial"; ctx.textAlign = "left"; ctx.textBaseline = "bottom"; ctx.save(); ctx.translate(this.x3, this.y3); ctx.rotate(Math.PI/4); ctx.fillText("✈", 0, 0); ctx.restore(); this.x3+=0.4; this.y3+=0.4; if(this.y3>150){ this.x3=-150; this.y3=-150; } // 旋转棒角度变换 if(this.angle>2*Math.PI){ this.angle=0; } }; } // 常规函数:角度得到弧度 function getRad(degree){ return degree/180*Math.PI; } /*---------------------------------- 最是人间留不住 朱颜辞镜花辞树 ...... 一生如牛不得闲 如闲已与山共眠 ----------------------------------*/ //--> </script>
【背景图】
这张背景图是用做雷达护板的,下载下来改名为67.copper.png,与代码配合使用。
END
分类:
Canvas与汽车仪表盘
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)