Introduction: Recently, the dial of the astronaut is very popular on the Internet. I saw a brother wrote it in SVG before, but I don’t know how to write it, so I decided to use canvas to write one. The effect is not bad, so I took it out for everyone to talk about!

Effect:

Train of thought

  1. Divided into two canvases to draw, canvas 1 is used to place motionless things (background, dial, text information);

  2. Canvas 2 is used to depict astronaut rotations and time updates (often redrawn);

  3. The rotation of the astronaut is to use a lot of pictures to switch, to achieve the effect of rotation.

Draw the dial

Circular constructor

Function Circle(o){this.x=0,// this. Y =0,// radius this.startAngle=0,// startAngle EndAngle =0,// endAngle this.anticlockwise=false; // Specify this.stroke=false; // Whether to stroke this.fill=false; // Whether to fill this.scaleX=1; // Scale X this.scaleY=1; This. rotate=0; this.init(o); Function (o){for(var key in o){this[key]=o[key]; Function (context){var CTX =context; // Get context ctx.save(); ctx.beginPath(); ctx.translate(this.x,this.y); If (this. The fill) {CTX. MoveTo (0, 0); } //ctx.moveTo(this.x,this.y); ctx.scale(this.scaleX,this.scaleY); / / set the zoom CTX. Arc (0, 0, enclosing r, enclosing startAngle, enclosing endAngle); If (this.lineWidth){ctx.lineWidth=this.lineWidth; } if(this.fill){// Whether to fill this.fillstyle? (ctx.fillStyle=this.fillStyle):null; ctx.fill(); } if(this.strokestyle){// Whether to stroke this.strokestyle? (ctx.strokeStyle=this.strokeStyle):null; ctx.stroke(); } ctx.restore(); return this; }Copy the code

Drawing code

/ / draw the dial SpaceMan. Prototype. DrawClock = function () {var x = y = 0, cilcle. x=this.w/2; y=this.h/2; // draw the big Circle cilcle = new Circle({x:x,// center x y:y,// center x r:250,// radius startAngle:0,// startAngle endAngle:2* math.pi,// endAngle lineWidth:2, fill:true, fillStyle:'#444444' }); this.renderArr.push(cilcle); // draw the second Circle cilcle = new Circle({x:x,// center x y:y,// center x r:220,// radius startAngle:0,// startAngle endAngle:2* math.pi,// endAngle lineWidth:2, fill:true, fillStyle:'#DFE6F0' }); this.renderArr.push(cilcle); }Copy the code

The page looks like this:

Draw dividing line

The constructor

Function Line(o){this.x=0,// this.y=0,// this.startX=0,// // this. EndX =0, this.endY=0; This. thin=false; // Set the fining factor 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; } // dash ctx.moveto (obj.startx, obj.starty); ctx.lineTo(obj.endX, obj.endY); ctx.stroke(); ctx.restore(); } return this; }Copy the code

Drawing code

/ / separation line drawing 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); }Copy the code

The effect of

Rendering text

The constructor

Function Text(o){this.x=0,//x this.y=0,//y this.disX=0,// y offset this. Text = "",// contents this.font=null; / / this font. TextAlign = null; // align 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); Rotate (-obj.angle* math.pi /180); rotate(-obj.angle* math.pi /180); } if(obj.font){ ctx.font=obj.font; } if(obj.textAlign){ ctx.textAlign=obj.textAlign; } if(obj.fill){// Whether to fill obj.fillstyle? (ctx.fillStyle=obj.fillStyle):null; ctx.fillText(obj.text,obj.disX,obj.disY); } if(obj. strokeStyle){// If obj.strokeStyle? (ctx.strokeStyle=obj.strokeStyle):null; ctx.strokeText(obj.text,obj.disX,obj.disY); } ctx.restore(); } return this; }Copy the code

draw

/ / assembly text SpaceMan. Prototype. DrawText = function () {var content = "", x = y = 0; / / the weather x = 230; Y =60,content=" good air "; 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, the content = "sunny days"; var text = new Text({ x:x, y:y, text:content, font:'20px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' });  this.renderArr.push(text); / / the temperature x = 230; 23 ° C y = 110, the content = ""; var text = new Text({ x:x, y:y, text:content, font:'18px ans-serif', textAlign:'left', fill:true, fillStyle:'#44444' });  this.renderArr.push(text); // Draw the minimum temperature x=285; Y = 110, the 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); // Draw Max temperature x=285; Y = 85, the 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); / / electricity 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); / / heart rate 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); Steps / / 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); / / sleep x = 110; Y = 395, the content = "sleep"; 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); / / distance x = 350; Y = 395, the content = "distance"; 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, the content = "9.22 km"; 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); }Copy the code

The effect is as follows:

Draw and decorate pictures

Image constructor

Function ImageDraw(o,obj){this.id= "", This. The image = 0, / / picture object (required) this. X = 0, / / picture slices start x position (show the whole picture) do not need to complete this. Sy = 0, / / picture section start y position (show the whole picture) do not need to complete this. SWidth = 0, // This. Dx =0,// this. Dy =0,// this. 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 (" draw pictures missing parameters "); return; } ctx.translate(obj.dx,obj.dy); if(getType(obj.sx)! ='undefined' && getType(obj.sy)! ='undefined' &&obj. SWidth &&obj. SHeight &&obj. DWidth &&obj. DHeight){ 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); // Original image, display without scaling} ctx.restore(); }} ImageDraw. Prototype. IsPoint = function (pos) {/ / mouse position x, y, respectively is greater than the dx, dy and x, y, respectively smaller than dWidth, dy dx + + dHeight if (pos) x > this. Dx && Y >this.dy && pos.x<this.dx+ this.dwidth && pos.y<this.dy+ this.dheight){return true; } return false; }Copy the code

draw

/ / assembly picture object information SpaceMan. Prototype. DrawOtherImg = function () {/ / draw power 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); }Copy the code

The effect at this time

Drawing astronauts

code

/ / assembly astronaut picture object information SpaceMan. The prototype. The drawImg = function () {var image = this. ImgObj [enclosing 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); }Copy the code

The effect of

Draw the time

The entry code

/ / draw date SpaceMan. Prototype. DrawDateTime = function () {enclosing drawHour (); // drawMinute this.drawMinute(); DrawSecond (); drawSecond(); // Draw seconds this.drawWeekDay(); This. drawMonthDate(); // drawMonthDate(); This. drawMonthDate2(); // Draw lunar calendar}Copy the code

Draw the hour

/ / draw hours SpaceMan. Prototype. DrawHour = function () {var content = this. Hour + ", "x = y = 0; / / h 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; // Draw: no 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); }Copy the code

Draw minutes, seconds

/ / draw the minutes 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; } / / draw the second SpaceMan. Prototype. DrawSecond = function () {var content = this. Second + ", "x = y = 0; / / second 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; }Copy the code

Draw the day and date

/ / draw the week 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; } / / draw the day SpaceMan. Prototype. DrawMonthDate = function () {var content. = this month + "-" + this. The date, x = y = 0; / / h 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; }Copy the code

Draw the lunar calendar

/ / draw the lunar day SpaceMan. Prototype. DrawMonthDate2 = function () {enclosing 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; }Copy the code

The effect is as follows:

Now that the overall effect is complete, the next step is to get moving

Astronaut rotation

  1. Setting a Scheduled Task
  2. Change the drawing one at a time

code

/ / the astronauts turned the SpaceMan. Prototype. HumanRotate = function () {/ / can be constantly updated picture this. ImageKey -; if(this.imageKey<this.startCount){ this.imageKey=60; } var img = this.renderArr2[0]; img.image = this.imgObj[this.imageKey]; this.render2(); }Copy the code

The effect

Time to update

Update seconds

/ / second SpaceMan. Prototype. UpdateSecond = function () {this. Second++; If (this.second==60){this.second=0; this.updateMinute(); } var content = this.second+""; content=(content.length==1? (0+content):content); this.secondObj.text=content; }Copy the code

Update the minutes

/ / minutes update 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; }Copy the code

Update the hours

/ / the clock update SpaceMan. Prototype. UpdateHour = function () {enclosing 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; }Copy the code

Renewal day, lunar calendar day

/ / update day SpaceMan. Prototype. UpdateDate = function () {var that = this, dateUpdateFlag = false, lastMonthDayLength, angleDis; this.date+=1; // Date increment 1 this.updateweekday (); / / update a few if (this. The date > enclosing currentMonthDayLength) {/ / is greater than the maximum number of days this month this. Just switch to 1, the date = 1; this.updateMonth(); } this.monthDateobj. text = this.month+"-"+this.date; this.updateMonthDate2(); } / / update the SpaceMan. Prototype. UpdateMonth = function () {var that = this; this.month+=1; if(this.month>12){ this.month=1; }} / / lunar date update 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; }Copy the code

Update the week

What day / / update the SpaceMan. Prototype. UpdateWeekDay = function () {this. Day + = 1; If (this.day>6){this.day=0; } this.weekdayobj. Text = this.weekarr [this.day]; }Copy the code

The final result

Source code download: pay attention to the public number [programming world mingshi hidden], reply [121] to download the code