canvas 纯js 绘制中国象棋棋盘
废话不多说,先上效果图:
思路:
1.把棋盘分为3部分。上半部分+“楚河汉界文字”+下半部分;
2.上半部分 的翻转平移 == 下半部分
3.分解上半部分;分为:四平八稳矩形框;十字格;米字格
4.分解“楚河汉界”部分;分为:“楚河” -Math.PI 旋转;“汉界”是 Math.PI 旋转
代码:
chess(); function chess(){ let canvas = document.getElementById("chess"); let chess = canvas.getContext("2d"); let width = chess.canvas.width; let height = chess.canvas.height; // 单边长 let sidelen = 24; // 左侧长度 = 竖直方向 let leftside = 4*sidelen; // 顶部长度 = 水平方向 let topside = 8*sidelen; chess.lineWidth = 2; for(let i=0; i<2; i++){ chess.save();
// 旋转平移得到下半部分 chess.rotate(i*Math.PI); chess.translate(-i*(topside+sidelen/4-chess.lineWidth),-i*(2*leftside+sidelen)); // 画一半的矩形框 drawChessRect(chess,sidelen); // 画十字格 for(let x =0; x<5; x++){ drawTen(chess,sidelen/4,Math.PI/2,4,sidelen,x); } for(let y =0; y<2; y++){ drawTenOther(chess,sidelen/4,Math.PI/2,4,sidelen,y); } // 米字格 drawMi(chess,sidelen); chess.restore(); } chess.font = "bold "+(sidelen/2+2)+"px microsoft yahei"; let fontArr = ["楚","河","汉","界"]; // 楚河 是 -Math.PI 旋转; 汉界 是 Math.PI 的旋转 for(let i=0; i<fontArr.length; i++){ if(i<2){ chess.save(); chess.beginPath(); chess.rotate(-Math.PI/2); chess.translate(-5*sidelen,0); chess.fillText(fontArr[i],4,sidelen*(1+2*i)); chess.closePath(); chess.restore(); } else { chess.save(); chess.beginPath(); chess.rotate(Math.PI/2); chess.translate(leftside,-topside); // 因为此处 i 的取值是 2,3;会造成误差。所以要-2处理 chess.fillText(fontArr[i],6,sidelen*(1+2*(i-2))); chess.closePath(); chess.restore(); } } } // 米字格 function drawMi(ctx,sidelen){ ctx.save(); ctx.translate(3*sidelen,0); for(let i=0; i<2; i++){ ctx.rotate(i*Math.PI/2); ctx.translate(0,-i*2*sidelen); ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(2*sidelen,2*sidelen); ctx.stroke(); ctx.closePath(); } ctx.restore(); } // 矩形框 function drawChessRect(ctx,len){ ctx.translate(2,2); for(let i=0; i<8;i++){ for(let j=0; j<4; j++){ ctx.strokeRect(i*len,j*len,len,len); } } } // 十字格 drawMi 循环 5 function drawTen(ctx,milen,angle,minum,sidelen,x){ ctx.save(); ctx.translate(x*2*sidelen,3*sidelen); for(let i=0; i<minum; i++){ drawTenLine(ctx,angle*i,milen); } ctx.restore(); } // 十字格 循环 2 ;因为translate 无规律 function drawTenOther(ctx,milen,angle,minum,sidelen,y){ ctx.save(); ctx.translate((y*6+1)*sidelen,2*sidelen); for(let i=0; i<minum; i++){ drawTenLine(ctx,angle*i,milen); } ctx.restore(); } // 十字格线条 function drawTenLine(ctx,angle,milen){ ctx.save(); ctx.beginPath(); ctx.rotate(angle); ctx.translate(ctx.lineWidth+1,ctx.lineWidth+1); ctx.moveTo(milen,0); ctx.lineTo(0,0); ctx.lineTo(0,milen); ctx.stroke(); ctx.closePath(); ctx.restore(); }
html:
<canvas id="chess" width="196" height="300"></canvas>
不足之处:
1、canvas font 如何设定特殊字体;本来“楚河汉界”打算用隶书的。
2、棋盘和 canvas 宽高数值如何规律关联?例如,“楚”文字的在 X 轴的定位,给的是 4;这个值完全靠眼缘~~
如果有知道的朋友,欢迎评论留言
共勉。