irpas技术客

用JavaScript实现网红太空人表盘(绝对详细、绝对原创),附源码下载_编程界明世隐_太空人表盘

未知 5455

引言:网上最近太空人表盘很火,之前看到有个兄弟用svg写的,但是我也不会这个啊,我就琢磨着用canvas写了一个,效果感觉还不错,拿出来大家唠唠! 效果图:

思路

分两个画布来绘制,画布1用来放置不动的东西(背景、表盘、文字信息);

画布2用来绘制太空人的转动和时间的更新(经常要重新绘制);

太空人的转动的话就是用很多图片来切换,达到转动的效果。

绘制表盘 圆形构造函数 //构造函数 function Circle(o){ this.x=0,//圆心X坐标 this.y=0,//圆心Y坐标 this.r=0,//半径 this.startAngle=0,//开始角度 this.endAngle=0,//结束角度 this.anticlockwise=false;//顺时针,逆时针方向指定 this.stroke=false;//是否描边 this.fill=false;//是否填充 this.scaleX=1;//缩放X比例 this.scaleY=1;//缩放Y比例 this.rotate=0; this.init(o); } //初始化 Circle.prototype.init=function(o){ for(var key in o){ this[key]=o[key]; } } //绘制 Circle.prototype.render=function(context){ var ctx=context;//获取上下文 ctx.save(); ctx.beginPath(); ctx.translate(this.x,this.y); if(this.fill){ ctx.moveTo(0,0); } //ctx.moveTo(this.x,this.y); ctx.scale(this.scaleX,this.scaleY);//设定缩放 ctx.arc(0,0,this.r,this.startAngle,this.endAngle);//画圆 if(this.lineWidth){//线宽 ctx.lineWidth=this.lineWidth; } if(this.fill){//是否填充 this.fillStyle?(ctx.fillStyle=this.fillStyle):null; ctx.fill(); } if(this.stroke){//是否描边 this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null; ctx.stroke(); } ctx.restore(); return this; } 绘制代码 //绘制表盘 SpaceMan.prototype.drawClock=function(){ var x=y=0,cilcle; x=this.w/2;y=this.h/2; //绘制外面的大圆 cilcle = new Circle({ x:x,//圆心X坐标 y:y,//圆心X坐标 r:250,//半径 startAngle:0,//开始角度 endAngle:2*Math.PI,//结束角度 lineWidth:2, fill:true, fillStyle:'#444444' }); this.renderArr.push(cilcle); //绘制第2个圆 cilcle = new Circle({ x:x,//圆心X坐标 y:y,//圆心X坐标 r:220,//半径 startAngle:0,//开始角度 endAngle:2*Math.PI,//结束角度 lineWidth:2, fill:true, fillStyle:'#DFE6F0' }); this.renderArr.push(cilcle); } 此时页面的效果:

绘制分隔线 构造函数 //直线的构造 function Line(o){ this.x=0,//x坐标 this.y=0,//y坐标 this.startX=0,//开始点x位置 this.startY=0, //开始点y位置 this.endX=0,//结束点x位置 this.endY=0;//结束点y位置 this.thin=false;//设置变细系数 this.init(o); } Line.prototype.init=function(o){ for(var key in o){ this[key]=o[key]; } } Line.prototype.render=function(ctx){ innerRender(this); function innerRender(obj){ ctx.save() ctx.beginPath(); ctx.translate(obj.x,obj.y); if(obj.thin){ ctx.translate(0.5,0.5); } if(obj.lineWidth){//设定线宽 ctx.lineWidth=obj.lineWidth; } if(obj.strokeStyle){ ctx.strokeStyle=obj.strokeStyle; } //划线 ctx.moveTo(obj.startX, obj.startY); ctx.lineTo(obj.endX, obj.endY); ctx.stroke(); ctx.restore(); } return this; } 绘制代码 //分隔线的 绘制 SpaceMan.prototype.drawClockLine=function(){ var x=y=0; var line = new Line({ x:x, y:y, startX:70, startY:120, endX:430, endY:120, strokeStyle:'#030609', lineWidth:3 }) this.renderArr.push(line); line = new Line({ x:x, y:y, startX:220, startY:30, endX:220, endY:120, strokeStyle:'#030609', lineWidth:3 }) this.renderArr.push(line); line = new Line({ x:x, y:y, startX:58, startY:360, endX:442, endY:360, strokeStyle:'#030609', lineWidth:3 }) this.renderArr.push(line); line = new Line({ x:x, y:y, startX:180, startY:410, endX:180, endY:460, strokeStyle:'#030609', lineWidth:3 }) this.renderArr.push(line); line = new Line({ x:x, y:y, startX:178, startY:410, endX:342, endY:410, strokeStyle:'#030609', lineWidth:3 }) this.renderArr.push(line); line = new Line({ x:x, y:y, startX:340, startY:410, endX:340, endY:360, strokeStyle:'#030609', lineWidth:3 }) this.renderArr.push(line); } 此时效果

绘制文字 构造函数 //文字的构造函数 function Text(o){ this.x=0,//x坐标 this.y=0,//y坐标 this.disX=0,//x坐标偏移量 this.disY=0,//y坐标偏移量 this.text='',//内容 this.font=null;//字体 this.textAlign=null;//对齐方式 this.init(o); } Text.prototype.init=function(o){ for(var key in o){ this[key]=o[key]; } } Text.prototype.render=function(context){ this.ctx=context; innerRender(this); function innerRender(obj){ var ctx=obj.ctx; ctx.save() ctx.beginPath(); ctx.translate(obj.x,obj.y); if(obj.angle){//根据旋转角度来执行旋转 ctx.rotate(-obj.angle*Math.PI/180); } if(obj.font){ ctx.font=obj.font; } if(obj.textAlign){ ctx.textAlign=obj.textAlign; } if(obj.fill){//是否填充 obj.fillStyle?(ctx.fillStyle=obj.fillStyle):null; ctx.fillText(obj.text,obj.disX,obj.disY); } if(obj.stroke){//是否描边 obj.strokeStyle?(ctx.strokeStyle=obj.strokeStyle):null; ctx.strokeText(obj.text,obj.disX,obj.disY); } ctx.restore(); } return this; } 绘制 //组装文字信息 SpaceMan.prototype.drawText=function(){ var content="",x=y=0; //天气 x=230;y=60,content="空气良好"; var text = new Text({ x:x, y:y, text:content, font:'bold 20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); x=230;y=85,content="晴天"; var text = new Text({ x:x, y:y, text:content, font:'20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //气温 x=230;y=110,content="23°C"; var text = new Text({ x:x, y:y, text:content, font:'18px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //绘制最小温度 x=285;y=110,content="18°"; var text = new Text({ x:x, y:y, text:content, font:'18px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //绘制最大温度 x=285;y=85,content="26°"; var text = new Text({ x:x, y:y, text:content, font:'18px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //电量 x=120;y=115,content="70%"; var text = new Text({ x:x, y:y, text:content, font:'bold 35px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //心率 x=65;y=305,content="80~128"; var text = new Text({ x:x, y:y, text:content, font:'20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); x=130;y=345,content="92"; var text = new Text({ x:x, y:y, text:content, font:'bold 30px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //步数 x=370;y=345,content="7032"; var text = new Text({ x:x, y:y, text:content, font:'bold 26px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //睡眠 x=110;y=395,content="睡眠"; var text = new Text({ x:x, y:y, text:content, font:'30px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); x=190;y=400,content="8h30m"; var text = new Text({ x:x, y:y, text:content, font:'BOLD 34px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); //距离 x=350;y=395,content="距离"; var text = new Text({ x:x, y:y, text:content, font:'30px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); x=210;y=445,content="9.22km"; var text = new Text({ x:x, y:y, text:content, font:'BOLD 32px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr.push(text); } 效果如下:

绘制修饰图片 图片构造函数 //图片对象ImageDraw构造函数 function ImageDraw(o,obj){ this.id='', this.image=0,//图片对象(必填) this.sx=0,//图片切片开始x位置(显示整个图片的时候不需要填) this.sy=0,//图片切片开始y位置(显示整个图片的时候不需要填) this.sWidth=0, //图片切片开始宽度(显示整个图片的时候不需要填) this.sHeight=0,//图片切片开始高度(显示整个图片的时候不需要填) this.dx=0, //图片目标x位置(必填) this.dy=0, //图片目标y位置(必填) this.dWidth=0,//图片目标显示宽度(宽度不缩放时不必填) this.dHeight=0//图片目标高度高度(高度不缩放时不必填) this.init(o,obj); } ImageDraw.prototype.init=function(o,obj){ this.lol=obj; for(var key in o){ this[key]=o[key]; } return this; } ImageDraw.prototype.render=function(context){ draw(context,this); function draw(context,obj) { var ctx=context; ctx.save(); if(!obj.image || getType(obj.dx)=='undefined' || getType(obj.dy)=='undefined'){ throw new Error("绘制图片缺失参数"); return; } ctx.translate(obj.dx,obj.dy); if(getType(obj.sx)!='undefined' && getType(obj.sy)!='undefined' && obj.sWidth && obj.sHeight && obj.dWidth && obj.dHeight){ //裁剪图片,显示时候有缩放 ctx.drawImage(obj.image, obj.sx, obj.sy, obj.sWidth, obj.sHeight, 0, 0, obj.dWidth, obj.dHeight); }else if(obj.dWidth && obj.dHeight){ ctx.drawImage(obj.image, 0, 0, obj.dWidth, obj.dHeight);//原始图片,显示时候有缩放 }else{ ctx.drawImage(obj.image,0, 0);//原始图片,显示时候无缩放 } ctx.restore(); } } ImageDraw.prototype.isPoint=function(pos){ //鼠标位置的x、y要分别大于dx、dy 且x、y要分别小于 dx+dWidth、dy+dHeight if(pos.x>this.dx && pos.y>this.dy && pos.x<this.dx+this.dWidth && pos.y<this.dy+this.dHeight ){//表示处于当前图片对象范围内 return true; } return false; } 绘制 //组装图片对象信息 SpaceMan.prototype.drawOtherImg=function(){ //绘制电量 var image = this.imgObj[66]; var img,x=y=0,sWidth=200,sHeight=200,dx=170,dy=45,dWidth=50,dHeight=50; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr.push(img); //绘制太阳 image = this.imgObj[62]; sWidth=200,sHeight=200,dx=340,dy=70,dWidth=50,dHeight=50; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr.push(img); //绘制最大温度 image = this.imgObj[65]; var img,x=y=0,sWidth=200,sHeight=200,dx=315,dy=70,dWidth=20,dHeight=20; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr.push(img); //绘制最小温度 image = this.imgObj[64]; var img,x=y=0,sWidth=200,sHeight=200,dx=315,dy=90,dWidth=20,dHeight=20; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr.push(img); //绘制心率 image = this.imgObj[61]; sWidth=200,sHeight=200,dx=70,dy=305,dWidth=60,dHeight=60; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr.push(img); //绘制步数 image = this.imgObj[63]; sWidth=200,sHeight=200,dx=320,dy=310,dWidth=50,dHeight=50; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr.push(img); } 此时的效果

绘制太空人 代码 //组装太空人图片对象信息 SpaceMan.prototype.drawImg=function(){ var image = this.imgObj[this.imageKey]; var img,x=y=0,sWidth=534,sHeight=598,dx=190,dy=200,dWidth=120,dHeight=134; img = new ImageDraw({image:image,sx:x,sy:y,sWidth:sWidth,sHeight:sHeight, dx:dx, dy:dy ,dWidth:dWidth,dHeight:dHeight},this); this.renderArr2.push(img); } 此时效果

绘制时间 入口代码 //绘制日期 SpaceMan.prototype.drawDateTime=function(){ this.drawHour();//绘制小时 this.drawMinute();//绘制分钟 this.drawSecond();//绘制秒钟 this.drawWeekDay();//绘制周 this.drawMonthDate();//绘制日 this.drawMonthDate2();//绘制农历 } 绘制小时 //绘制小时 SpaceMan.prototype.drawHour=function(){ var content=this.hour+"",x=y=0; //小时 x=120;y=190, content=(content.length==1?(0+content):content); var text = new Text({ x:x, y:y, text:content, font:'bold 80px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); this.hourObj=text; //绘制 :号 x=220;y=175, content=":"; text = new Text({ x:x, y:y, text:content, font:'bold 60px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); } 绘制分钟、秒钟 //绘制分钟 SpaceMan.prototype.drawMinute=function(){ var content=this.minute+"",x=y=0; //分 x=235;y=190, content=(content.length==1?(0+content):content); var text = new Text({ x:x, y:y, text:content, font:'bold 80px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); this.minuteObj=text; } //绘制秒钟 SpaceMan.prototype.drawSecond=function(){ var content=this.second+"",x=y=0; //秒 x=340;y=190, content=(content.length==1?(0+content):content); var text = new Text({ x:x, y:y, text:content, font:'bold 35px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); this.secondObj=text; } 绘制星期、日期 //绘制星期 SpaceMan.prototype.drawWeekDay=function(){ var x=y=0; x=350;y=270, content=this.weekArr[this.day]; var text = new Text({ x:x, y:y, text:content, font:'20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); this.weekDayObj=text; } //绘制日 SpaceMan.prototype.drawMonthDate=function(){ var content=this.month+"-"+this.date,x=y=0; //小时 x=400;y=270, content=(content.length==1?(0+content):content); var text = new Text({ x:x, y:y, text:content, font:'20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); this.monthDateObj=text; } 绘制农历 //绘制农历日 SpaceMan.prototype.drawMonthDate2=function(){ this.lunarObj = new LunarDay(); var lunarDay = this.lunarObj.getLunarDay(this.year,this.month,this.date); var lunarDayArr = lunarDay.split(" "); var content= lunarDayArr[1],x=y=0; x=350;y=240; text = new Text({ x:x, y:y, text:content, font:'20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' }); this.renderArr2.push(text); this.lunarDateObj=text; } 效果如下 :

到现在的话整体效果已经完成了,接下来就是要动起来 太空人转动 设置定时任务每次更换一张图片绘制 代码 //太空人转动 SpaceMan.prototype.humanRotate=function(){ //不断的更新图片即可 this.imageKey--; if(this.imageKey<this.startCount){ this.imageKey=60; } var img = this.renderArr2[0]; img.image = this.imgObj[this.imageKey]; this.render2(); } 效果

时间更新 更新秒 //秒钟转动 SpaceMan.prototype.updateSecond=function(){ this.second++; if(this.second==60){//到达60以后设置为0 this.second=0; this.updateMinute();//更新分钟 } var content = this.second+""; content=(content.length==1?(0+content):content); this.secondObj.text=content; } 更新分钟 //分钟更新 SpaceMan.prototype.updateMinute=function(){ this.minute++; if(this.minute==60){ this.minute=0; this.updateHour(); } var content = this.minute+""; content=(content.length==1?(0+content):content); this.minuteObj.text=content; } 更新小时 //时钟更新 SpaceMan.prototype.updateHour=function(){ this.hour+=1; if(this.hour==24){ this.hour=0; this.updateDate(); } var content = this.hour+""; content=(content.length==1?(0+content):content); this.hourObj.text=content; } 更新日、农历日 //更新日 SpaceMan.prototype.updateDate=function(){ var that=this,dateUpdateFlag=false,lastMonthDayLength,angleDis; this.date+=1;//日期递增1 this.updateWeekDay();//更新周几 if(this.date>this.currentMonthDayLength){//大于本月最大天数就切换到1日 this.date=1; this.updateMonth();//更新月份 } this.monthDateObj.text = this.month+"-"+this.date; this.updateMonthDate2(); } //月更新 SpaceMan.prototype.updateMonth=function(){ var that=this; this.month+=1; if(this.month>12){ this.month=1; } } //农历日期更新 SpaceMan.prototype.updateMonthDate2=function(){ var lunarDay = this.lunarObj.getLunarDay(this.year,this.month,this.date); var lunarDayArr = lunarDay.split(" "); var content= lunarDayArr[1]; this.lunarDateObj.text=content; } 更新星期 //更新星期几 SpaceMan.prototype.updateWeekDay=function(){ this.day+=1; //大于6则重置 if(this.day>6){ this.day=0; } //数组中获取周几 this.weekDayObj.text=this.weekArr[this.day]; } 最终效果

兄弟们给个三连支持一下,谢谢哇! 源码下载

关注下方公众号,回复?121?下载代码

★?更多源码

?? 基于canvas的手风琴特效(附源码)?

? 抖音很火的华为太空人表盘(附源码)?

? 基于JavaScript页面动态验证码(附源码)?

? 基于JavaScript的拖动滑块拼图验证(附源码)?

? 基于JavaScript的幸运大转盘(附源码)?

? 抖音很火的罗盘时钟(附源码)?

? 基于JavaScript的俄罗斯方块小游戏(附源码)?

? 基于JavaScript的贪吃蛇游戏(附源码)?

? 基于JavaScript的拼图游戏(附源码)?

? 用JavaScript给女儿做的烟花特效(附源码)?

? 老父亲给女儿做的下雪特效,满足女儿看雪的愿望(附源码)?

? 雷达扫描特效(附源码)?

? 香港黄金配角吴孟达去世,80后程序员以轮播图来悼念达叔,达叔一路走好!(附源码)?

? 仿抖音刷新进度条(附源码)?

? 仿头条方形刷新进度条(附源码)?

? 仿360加速球、水波评分特效(附源码)?

? 基于canvas的刮刮卡(附源码)?

? 原生js写的左侧飞入拼图特效,你是喜欢美女单飞还是双飞(附源码)?

? 用js写的旋转木马,在新年献给各位刚登基的皇帝,让你的后宫转起来!程序员就是可以为所欲为!(附源码)?

? 用js写的轮播图,八位女明星,你翻谁的牌,程序员就是可以为所欲为!(附源码)?

? 原生js实现美女拼图,把美女老婆抱回家,5个美女够不够!程序员就是可以为所欲为!(附源码)?

? 用js仿探探拖拽卡片的效果、飞卡片的效果,感觉挺酷,最后有美女看哦!(附源码)?

? 老婆说程序员不懂浪漫,程序员默默拿起了键盘,这就亲手带你去看流星雨,女人真会影响拔刀的速度(附源码)?

? 学生成绩管理系统(jsp+jquery+java+mysql+tomcat)有源码,你的毕设我的心(附源码)?


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #太空人表盘 #绘制表盘圆形构造函数构造函数 #function #Circleothisx0 #圆心