【关键点】
底图的查找和多次尝试、文字描边。
【成图】
【代码】
<!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head> <title>使用HTML5/Canvas绘制铜质钢底24周年纪念章</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> <img id="myImg1" src="159-1.jpg" style="display:none;"/> <img id="myImg2" src="159-2.jpg" style="display:none;"/> </div> </body> </html> <script type="text/javascript"> <!-- /***************************************************************** * 将全体代码(从<!DOCTYPE到script>)拷贝下来,粘贴到文本编辑器中, * 另存为.html文件,再用chrome浏览器打开,就能看到实现效果。 ******************************************************************/ // canvas的绘图环境 var ctx; // 高宽 const WIDTH=512; const HEIGHT=512; // 舞台对象 var stage; //------------------------------- // 初始化 //------------------------------- function init(){ // 获得canvas对象 var canvas=document.getElementById('myCanvas'); 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.init=function(){ } // 更新 this.update=function(){ } // 画背景 this.paintBg=function(ctx){ ctx.clearRect(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT);// 清屏 writeText(ctx,WIDTH/2-30,HEIGHT/2-10,"逆火原创","8px consolas","black");// 版权 } // 画前景 this.paintFg=function(ctx){ // 外凸圈 var r=244; ctx.save(); ctx.beginPath(); ctx.arc(0,0,r,0,Math.PI*2,false); ctx.closePath(); var lgrd=ctx.createLinearGradient(-r,-r,2*r,2*r); lgrd.addColorStop(0,"rgb(255,230,111)"); lgrd.addColorStop(1,"rgb(0,0,0)"); ctx.fillStyle=lgrd; ctx.fill(); // 分隔圈 ctx.save(); ctx.beginPath(); ctx.arc(0,0,241,0,Math.PI*2,false); ctx.closePath(); ctx.strokeStyle="rgb(174,143,0)"; ctx.stroke(); // 中圈 ctx.save(); ctx.rotate(Math.PI*5/4); var r=240; ctx.beginPath(); ctx.arc(0,0,r,0,Math.PI*2,false); ctx.closePath(); ctx.clip(); var img=document.getElementById("myImg1"); ctx.drawImage(img,0,0,300,300,-r,-r,2*r,2*r); ctx.restore(); // 内凹圈 var r=144; ctx.beginPath(); ctx.arc(0,0,r,0,Math.PI*2,false); ctx.closePath(); var lgrd=ctx.createLinearGradient(-r,-r,2*r,2*r); lgrd.addColorStop(0,"rgb(151,124,0)"); lgrd.addColorStop(1,"rgb(255,230,111)"); ctx.fillStyle=lgrd; ctx.fill(); // 分隔圈 ctx.beginPath(); ctx.arc(0,0,141,0,Math.PI*2,false); ctx.closePath(); ctx.strokeStyle="rgb(65,42,36)" ctx.stroke(); // 内圈 ctx.save(); ctx.rotate(1*Math.PI+Math.PI/4); var r=140; ctx.beginPath(); ctx.arc(0,0,r,0,Math.PI*2,false); ctx.closePath(); ctx.clip(); var img=document.getElementById("myImg2"); ctx.drawImage(img,50,200,2*r,2*r,-r,-r,2*r,2*r); ctx.restore(); // 加个蒙版 ctx.beginPath(); ctx.arc(0,0,r,0,Math.PI*2,false); ctx.closePath(); ctx.fillStyle="rgba(25,25,25,0.1)"; ctx.fill(); // 上半圈文字 var words="CELEBRATING"; var arr=words.split(""); for(var i=0;i<arr.length;i++){ var letter=arr[i]; var theta=i*Math.PI/180*12.5+Math.PI+Math.PI/180*30; var r=165; var x=r*Math.cos(theta); var y=r*Math.sin(theta); ctx.save(); ctx.translate(x,y); ctx.rotate(theta+Math.PI/2); ctx.scale(1,0.8); ctx.textBaseline="bottom"; ctx.textAlign="center"; ctx.font = "48px Stencil Std"; ctx.fillStyle="rgb(67,42,20)"; ctx.fillText(letter,0,0); ctx.strokeStyle="rgb(255,160,66)"; ctx.strokeText(letter,0,0); ctx.restore(); } // 下半圈文字 var words="aniversary"; var arr=words.split(""); for(var i=0;i<arr.length;i++){ var letter=arr[i]; var theta=-i*Math.PI/180*12.5+Math.PI-Math.PI/180*36; var r=214; var x=r*Math.cos(theta); var y=r*Math.sin(theta); ctx.save(); ctx.translate(x,y); ctx.rotate(theta-Math.PI/2); ctx.scale(1,0.8); ctx.textBaseline="bottom"; ctx.textAlign="center"; ctx.font = "48px Stencil Std"; ctx.fillStyle="rgb(67,42,20)"; ctx.fillText(letter,0,0); ctx.strokeStyle="rgb(255,160,66)"; ctx.strokeText(letter,0,0); ctx.restore(); } // 两侧五星 draw5Star(ctx,-189,0,21); ctx.fillStyle="rgb(67,42,20)"; ctx.fill(); ctx.strokeStyle="rgb(255,160,66)"; ctx.stroke(); draw5Star(ctx,189,0,21); ctx.fillStyle="rgb(67,42,20)"; ctx.fill(); ctx.strokeStyle="rgb(255,160,66)"; ctx.stroke(); // 24 var x=-10,y=55; var word="24"; ctx.textBaseline="bottom"; ctx.textAlign="center"; ctx.font = "96px Stencil Std"; ctx.fillStyle="rgb(67,42,20)"; ctx.fillText(word,x,y); ctx.strokeStyle="rgb(255,160,66)"; ctx.strokeText(word,x,y); // th var x=70,y=-15; var word="th"; ctx.textBaseline="bottom"; ctx.textAlign="center"; ctx.font = "36px consolas"; ctx.fillStyle="rgb(67,42,20)"; ctx.fillText(word,x,y); ctx.strokeStyle="rgb(255,160,66)"; ctx.strokeText(word,x,y); // 24颗星 var r=120; for(var i=0;i<24;i++){ var theta=i*Math.PI*2/24; var x=r*Math.cos(theta); var y=r*Math.sin(theta); draw5Star(ctx,x,y,8); ctx.fillStyle="rgb(255,215,0)"; ctx.fill(); } } } /*-------------------------------------------------- 函数:绘制正五角星的推荐画法 ctx:绘图上下文 x:五角星中心横坐标 y:五角星中心纵坐标 R:五角星中心到顶点的距离 ---------------------------------------------------*/ function draw5Star(ctx,x,y,R){ var r=R*Math.sin(Math.PI/10)/Math.sin(Math.PI/10*7); var arr=[0,0,0,0,0,0,0,0,0,0]; // 顶五点 for(var i=0;i<5;i++){ var theta=i*Math.PI/5*2-Math.PI/10; var x1=R*Math.cos(theta)+x; var y1=R*Math.sin(theta)+y; arr[i*2]=createPt(x1,y1); } // 内五点 for(var i=0;i<5;i++){ var theta=i*Math.PI/5*2+Math.PI/10; var x1=r*Math.cos(theta)+x; var y1=r*Math.sin(theta)+y; arr[i*2+1]=createPt(x1,y1); } ctx.beginPath(); for(var i=0;i<arr.length;i++){ ctx.lineTo(arr[i].x,arr[i].y); } ctx.closePath(); } /*---------------------------------------------------------- 函数:创建一个二维坐标点 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>
【底图】
159-1.jpg
159-2.jpg