【成圖】





【代碼】
<!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 onload="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;//-------------------------------
// 初始化
//-------------------------------
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);// 清屏 }// 畫前景this.paintFg=function(ctx){// 底色/*ctx.save();ctx.fillStyle = "white";ctx.fillRect(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT);ctx.restore();*/const R=220;//基準尺寸// #1 上下漸變金盤ctx.save(); var r=R*1.00;var gnt=ctx.createLinearGradient(0,-r,0,r);gnt.addColorStop(0,"rgb(225,199,125)");gnt.addColorStop(1,"rgb(150,103,49)");drawSolidCircle(ctx,0,0,r,gnt);ctx.restore();// #2 鋸齒邊ctx.save(); var r=R*1.00;ctx.fillStyle="black";// 1drawSawtoothLoop(ctx,0,0,20,r*1.05,r*0.95); ctx.fill();ctx.fillStyle="rgb(243,233,146)";// 2drawSawtoothLoop(ctx,0,0,20,r*1.03,r*0.93); ctx.fill();ctx.fillStyle="black";// 3drawSawtoothLoop(ctx,0,0,20,r*1.01,r*0.91); ctx.fill();ctx.restore();// #3 上下漸變金圈ctx.save(); var r=R*0.85;var gnt=ctx.createLinearGradient(0,-r,0,r);gnt.addColorStop(0,"rgb(221,193,119)");gnt.addColorStop(0.25,"rgb(177,130,58)");gnt.addColorStop(0.375,"rgb(228,211,131)");gnt.addColorStop(0.5,"rgb(144,91,41)");gnt.addColorStop(0.625,"rgb(169,108,41)");gnt.addColorStop(0.75,"rgb(216,158,58)");gnt.addColorStop(1,"rgb(220,169,64)");drawSolidCircle(ctx,0,0,r,gnt);drawSolidCircle(ctx,0,0,R*0.83,"black");ctx.restore();// #4 環狀橄欖枝ctx.save(); var n=32;var r=R*0.70;drawLeftOliver(ctx,0,0,r,n,Math.PI/2,Math.PI/2*3-Math.PI/18,Math.PI/6,Math.PI/4,gnt);// 左枝drawRightOliver(ctx,0,0,r,n,-Math.PI/2+Math.PI/18,Math.PI/2,Math.PI/6,Math.PI/4,gnt);// 右枝ctx.fillStyle=gnt;// 上方十字drawIronCross(ctx,0,-r,r*0.18,r*0.075);ctx.fill();drawSolidCircle(ctx,0,r,R/220*9,gnt);// 下方圓球ctx.restore();// #5 玻璃光ctx.save(); var r=R*0.81;var gnt=ctx.createLinearGradient(0,-r,0,r);gnt.addColorStop(0,"rgba(255,255,255,0.3)");gnt.addColorStop(0.5,"rgba(255,255,255,0.15)");gnt.addColorStop(1,"rgba(255,255,255,0.0)");drawSolidCircle(ctx,0,0,r,gnt);drawSolidCircle(ctx,0,0,R*0.60,"black");ctx.restore();// #6 上下漸變金圈ctx.save(); var r=R*0.58;var gnt=ctx.createLinearGradient(0,-r,0,r);gnt.addColorStop(0,"rgb(255,253,162)");gnt.addColorStop(0.5,"rgb(212,175,68)");gnt.addColorStop(1,"rgb(171,137,48)");drawSolidCircle(ctx,0,0,r,gnt);drawSolidCircle(ctx,0,0,R*0.565,"black");ctx.restore();// #7 德國旗ctx.save(); var r=R*0.545;ctx.beginPath();ctx.arc(0,0,r,0,Math.PI*2,false);ctx.clip();var h=2*r;// 高寬var w=3*r;const N=3;var colors=["rgb(7,3,2)","rgb(190,25,39)","rgb(233,203,57)"];// 黑紅黃三色for(var i=0;i<N;i++){ctx.fillStyle=colors[i];drawRect(ctx,0,-h/3+i*h/3,w,h/3);ctx.fill();} ctx.restore();// #8 月形玻璃光ctx.save(); var r=R*0.545;var center=createPt(0,0);var c=createPt2(center.x,center.y,r,Math.PI/6);var b=createPt2(center.x,center.y,r,Math.PI/2+Math.PI/6);var a=createPt2(center.x,center.y,r,-Math.PI/3);var gnt=ctx.createLinearGradient(0,-r,0,b.y);gnt.addColorStop(0,"rgba(255,255,255,0.3)");gnt.addColorStop(0.4,"rgba(255,255,255,0.15)");gnt.addColorStop(1,"rgba(255,255,255,0.0)");ctx.fillStyle=gnt;ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.arc(center.x,center.y,r,-Math.PI/3,Math.PI/2+Math.PI/6,true);ctx.arc(c.x,c.y,r*Math.sqrt(2),Math.PI-Math.PI/12,-Math.PI/2-Math.PI/12,false);ctx.fill();ctx.restore();writeText(ctx,WIDTH/2-30,HEIGHT/2-5,"逆火制圖","8px consolas","lightgrey");// 版權}
}/*----------------------------------------------------------
函數:用于繪制鐵十字輪廓
ctx:繪圖上下文
x,y:鐵十字矩形中心坐標
sideLength:容納鐵十字的正方形邊長
thickness:鐵十字在正方形邊上的厚度
----------------------------------------------------------*/
function drawIronCross(ctx,x,y,sideLength,thickness){var r=sideLength*sideLength/thickness/2+thickness/8;var alpha=Math.asin(sideLength/2/r);var beta=Math.asin((1+0.25*thickness/r)/Math.sqrt(2))-Math.PI/4;ctx.save();ctx.translate(x,y);var a=createPt(sideLength/2,-thickness/2);var b=createPt(sideLength/2,+thickness/2);ctx.beginPath();ctx.moveTo(sideLength/2,-thickness/2);ctx.lineTo(sideLength/2,+thickness/2);ctx.arc(0,r+thickness/4,r,alpha-Math.PI/2,-Math.PI/2+beta,true);ctx.arc(r+thickness/4,0,r,Math.PI-beta,Math.PI-alpha,true);ctx.lineTo(-thickness/2,sideLength/2);ctx.arc(-r-thickness/4,0,r,alpha,beta,true);ctx.arc(0,r+thickness/4,r,-Math.PI/2-beta,-Math.PI/2-alpha,true);ctx.lineTo(-sideLength/2,-thickness/2);ctx.arc(0,-r-thickness/4,r,Math.PI/2+alpha,Math.PI/2+beta,true);ctx.arc(-r-thickness/4,0,r,-beta,-alpha,true);ctx.lineTo(thickness/2,-sideLength/2);ctx.arc(r+thickness/4,0,r,Math.PI+alpha,Math.PI+beta,true);ctx.arc(0,-r-thickness/4,r,Math.PI/2-beta,Math.PI/2-alpha,true);ctx.closePath();ctx.restore();
}/*----------------------------------------------------------
函數:畫順時針橄欖枝
x:橫坐標
y:縱坐標
r:橄欖枝中心半徑
n:葉片對數
start:起始角度
end:中止角度
alpha: 葉片中線到圓弧的角度
beta:葉片中線到圓弧的角度
color:葉片顏色
----------------------------------------------------------*/
function drawLeftOliver(ctx,x,y,r,n,start,end,alpha,beta,color){const R=r; // 橄欖枝中心半徑var N=n; // 有N對葉片 const START=start; // 起始角度const END=end; // 中止角度const STEP=(END-START)/N;// 步長 const ALPHA=alpha; // 葉片中線到圓弧的角度const L=R/8; // 葉片長度const BETA=beta; // 葉片中線到圓弧的角度ctx.save(); ctx.translate(x,y);ctx.rotate(STEP);ctx.lineWidth=1;ctx.strokeStyle=color;// 畫中心圈ctx.beginPath();for(var i=-1;i<=N;i++){var theta=START+STEP*i;var r=R;var a=createPt(r*Math.cos(theta),r*Math.sin(theta));ctx.lineTo(a.x,a.y); }ctx.stroke();// 畫外側葉子for(var i=0;i<N;i++){var theta=START+STEP*i;var r=R;var a=createPt(r*Math.cos(theta),r*Math.sin(theta));r=L/9;var angle=theta+ALPHA;var b=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta+ALPHA+BETA;var d=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta+ALPHA-BETA;var e=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L;angle=theta+ALPHA;var c=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));ctx.fillStyle=color;ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.quadraticCurveTo(d.x,d.y,c.x,c.y);ctx.quadraticCurveTo(e.x,e.y,b.x,b.y); ctx.closePath(); ctx.fill();}// 畫內側葉子for(var i=0;i<N;i++){var theta=START+STEP*i;var r=R;var a=createPt(r*Math.cos(theta),r*Math.sin(theta));r=L/9;var angle=theta-ALPHA+Math.PI;var b=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta-ALPHA+Math.PI+BETA;var d=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta-ALPHA+Math.PI-BETA;var e=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L;angle=theta-ALPHA+Math.PI;var c=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));ctx.fillStyle=color;ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.quadraticCurveTo(d.x,d.y,c.x,c.y);ctx.quadraticCurveTo(e.x,e.y,b.x,b.y); ctx.closePath(); ctx.fill();} ctx.restore();
}/*----------------------------------------------------------
函數:畫逆時針橄欖枝
x:橫坐標
y:縱坐標
r:橄欖枝中心半徑
n:葉片對數
start:起始角度
end:中止角度
alpha: 葉片中線到圓弧的角度
beta:葉片中線到圓弧的角度
color:葉片顏色
----------------------------------------------------------*/
function drawRightOliver(ctx,x,y,r,n,start,end,alpha,beta,color){const R=r; // 橄欖枝中心半徑var N=n; // 有N對葉片 const START=start; // 起始角度const END=end; // 中止角度const STEP=(END-START)/N;// 步長 const ALPHA=alpha; // 葉片中線到圓弧的角度const L=R/8; // 葉片長度const BETA=beta; // 葉片中線到圓弧的角度ctx.save();ctx.translate(x,y);ctx.lineWidth=1;ctx.strokeStyle=color;// 畫中心圈ctx.beginPath();for(var i=-1;i<=N;i++){var theta=START+STEP*i;var r=R;var a=createPt(r*Math.cos(theta),r*Math.sin(theta));ctx.lineTo(a.x,a.y); }ctx.stroke();// 畫外側葉子for(var i=0;i<N;i++){var theta=START+STEP*i;var r=R;var a=createPt(r*Math.cos(theta),r*Math.sin(theta));r=L/9;var angle=theta-ALPHA;var b=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta-ALPHA+BETA;var d=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta-ALPHA-BETA;var e=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L;angle=theta-ALPHA;var c=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));ctx.fillStyle=color;ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.quadraticCurveTo(d.x,d.y,c.x,c.y);ctx.quadraticCurveTo(e.x,e.y,b.x,b.y); ctx.closePath(); ctx.fill();}// 畫內側葉子for(var i=0;i<N;i++){var theta=START+STEP*i;var r=R;var a=createPt(r*Math.cos(theta),r*Math.sin(theta));r=L/9;var angle=theta+ALPHA-Math.PI;var b=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta+ALPHA-Math.PI+BETA;var d=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L/9*4/Math.cos(BETA);angle=theta+ALPHA-Math.PI-BETA;var e=createPt(b.x+r*Math.cos(angle),b.y+r*Math.sin(angle));r=L;angle=theta+ALPHA-Math.PI;var c=createPt(a.x+r*Math.cos(angle),a.y+r*Math.sin(angle));ctx.fillStyle=color;ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.quadraticCurveTo(d.x,d.y,c.x,c.y);ctx.quadraticCurveTo(e.x,e.y,b.x,b.y); ctx.closePath(); ctx.fill();} ctx.restore();
}/*----------------------------------------------------------
基本函數:用于繪制鋸齒環
ctx:繪圖上下文
x:圖形中心橫坐標
y:圖形中心縱坐標
n:齒輪齒數
outerRadius:齒輪外徑
innerRadius:齒輪內徑
----------------------------------------------------------*/
function drawSawtoothLoop(ctx,x,y,n,outerRadius,innerRadius){var angle=Math.PI/n;var gearArr=new Array();// 創建點數組for(var i=0;i<n*2;i++){var alpha=Math.PI/n*i;var bata=alpha+angle;var x1,y1,x2,y2;if(i%2==1){x1=innerRadius*Math.cos(alpha);y1=innerRadius*Math.sin(alpha);x2=outerRadius*Math.cos(bata);y2=outerRadius*Math.sin(bata); }else{ x1=outerRadius*Math.cos(alpha);y1=outerRadius*Math.sin(alpha);x2=innerRadius*Math.cos(bata);y2=innerRadius*Math.sin(bata);}gearArr.push({x:x1,y:y1});gearArr.push({x:x2,y:y2});}ctx.beginPath();// 繪制輪廓for(var i=0;i<gearArr.length;i++){ctx.lineTo(gearArr[i].x,gearArr[i].y);}ctx.closePath();
}/*----------------------------------------------------------
基本函數:用于繪制矩形
ctx:繪圖上下文
x:矩形中心橫坐標
y:矩形中心縱坐標
width:矩形寬
height:矩形高
----------------------------------------------------------*/
function drawRect(ctx,x,y,width,height){ctx.beginPath();ctx.moveTo(x-width/2,y-height/2);ctx.lineTo(x+width/2,y-height/2);ctx.lineTo(x+width/2,y+height/2);ctx.lineTo(x-width/2,y+height/2);ctx.closePath();
}/*----------------------------------------------------------
基本函數:用于繪制實心圓
ctx:繪圖上下文
x:矩形中心橫坐標
y:矩形中心縱坐標
r:圓半徑
style:填充圓的方案
----------------------------------------------------------*/
function drawSolidCircle(ctx,x,y,r,style){ctx.fillStyle=style;ctx.beginPath();ctx.arc(x,y,r,0,Math.PI*2,false);ctx.closePath();ctx.fill();
}/*----------------------------------------------------------
基本函數:創建一個二維坐標點
baseX:基準點橫坐標
baseY:基準點縱坐標
radius:當前點到基準點的距離
theta:當前點到基準點的角度
Pt即Point
----------------------------------------------------------*/
function createPt2(baseX,baseY,radius,theta){var retval={};retval.x=baseX+radius*Math.cos(theta);retval.y=baseY+radius*Math.sin(theta);return retval;
}/*----------------------------------------------------------
基本函數:創建一個二維坐標點
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