前些年的时候,突然对Canvas感兴趣,利用空闲时间做一些Canvas小例子进行练习,仅供学习分享使用。如有不足之处,还请指正。
什么是 Canvas?
HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。画布是一个矩形区域,您可以控制其每一像素。canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
创建 Canvas 元素及JavaScript对象
向 HTML5 页面添加 canvas 元素。规定元素的 id、宽度和高度,如下所示:
<canvas id="myCanvas" width="200" height="100"></canvas>
JavaScript 使用 id 来寻找 canvas 元素:
var c=document.getElementById("myCanvas");
然后,创建 context 对象:
var cxt=c.getContext("2d");
注意:getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
实例一、灯笼绘制
以下是一个灯笼,并作了简要的说明。
具体绘制思路在页面上有说明,不再赘述,代码如下:
<script type="text/javascript"> //绘制椭圆 function ParamEllipse(context, x, y, a, b) { //max是等于1除以长轴值a和b中的较大者 //i每次循环增加1/max,表示度数的增加 //这样可以使得每次循环所绘制的路径(弧线)接近1像素 var step = (a > b) ? 1 / a : 1 / b; context.fillStyle = "#ff0000"; context.beginPath(); context.moveTo(x + a, y); //从椭圆的左端点开始绘制 for (var i = 0; i < 2 * Math.PI; i += step) { //参数方程为x = a * cos(i), y = b * sin(i), //参数为i,表示度数(弧度) context.lineTo(x + a * Math.cos(i), y + b * Math.sin(i)); } context.closePath(); context.stroke(); context.fill(); context.closePath(); }; //绘制矩形 function FillRect(context, x, y, w, h, flag) { var grd = context.createLinearGradient(x+w/2, y, x + w/2, y + h); if (flag) { grd.addColorStop(0, "yellow"); grd.addColorStop(1, "red"); } else { grd.addColorStop(0, "red"); grd.addColorStop(1, "yellow"); } context.fillStyle = grd; context.fillRect(x, y, w, h); } //绘制线条 function SetLine(ctx, x, y, x1, y1) { ctx.beginPath(); ctx.strokeStyle = "yellow"; ctx.moveTo(x,y); ctx.lineTo(x1,y1); ctx.stroke(); ctx.closePath(); } window.onload = function () { var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); var startX = 150; //中心坐标x var startY = 300; //中心坐标y var pWidth = 120; //椭圆长轴 var pHeigth = 80; //椭圆形短轴 var fWidth = 120; //矩形宽 var fheight = 40; //矩形高 //绘制椭圆 ParamEllipse(ctx, startX, startY, pWidth, pHeigth); //在椭圆上方和下方绘制长方形,且有一半的高度和椭圆重叠 FillRect(ctx, startX - fWidth / 2, startY - pHeigth - (fheight / 2), fWidth, fheight, true); FillRect(ctx, startX - fWidth / 2, startY + pHeigth - (fheight / 2), fWidth, fheight, false); //在矩形下方绘制线条,8个单位一条线,长度为40,均匀分布在矩形下方 var lLen = fheight; //画线的范围始终在矩形之下 var lInterval = 8; //线与线之间的间隔 for (var i = 0; i < (fWidth / 8) + 1; i++) { SetLine(ctx, startX - fWidth / 2 + i * lInterval, startY + pHeigth + fheight / 2, startX - fWidth / 2 + i * lInterval, startY + pHeigth + fheight / 2 + lLen); } //对三部分进行拆解 //1. 上矩形 var right = 380; FillRect(ctx, startX - fWidth / 2 + right, startY - pHeigth - (fheight / 2) - 150, fWidth, fheight, true); //2. 中椭圆 ParamEllipse(ctx, startX + right, startY - 50, pWidth, pHeigth); //3. 下矩形 FillRect(ctx, startX - fWidth / 2 + right, startY + pHeigth - (fheight / 2) + 50, fWidth, fheight, false); //4. 下线 for (var i = 0; i < (fWidth / 8) + 1; i++) { SetLine(ctx, startX - fWidth / 2 + i * lInterval + right, startY + pHeigth + fheight / 2 + 100, startX - fWidth / 2 + i * lInterval + right, startY + pHeigth + fheight / 2 + lLen + 100); } //画线,将其连接起来 var lsX = startX + pWidth + 20; var lsY = startY; var leX = startX + pWidth + 20 + 100; var leY = startY; SetLine(ctx, lsX, startY - 30, leX - 30, leY - 150); SetLine(ctx, lsX, startY - 15, leX, leY - 50); SetLine(ctx, lsX, startY + 15, leX, leY + 100); SetLine(ctx, lsX, startY + 30, leX - 30, leY + 150); //左上标写上说明 ctx.font = "35px Arial"; var t = "灯笼组成--2016-11-13"; ctx.fillText(t, 50, 50); } </script>
实例二、绘制时钟
绘制一个走动的时钟,具体如下图所示:
具体思路在上图已有说明,代码如下:
<script type="text/javascript"> //绘制圆形的弧度,ctx 为绘制环境,x,y为绘制中心,r为绘制半径,st为起始弧度,end为结束弧度 function circle(ctx, x, y, r, st, end, w) { ctx.lineWidth = w; ctx.beginPath(); ctx.moveTo(x, y); ctx.arc(x, y, r, st, end, true); ctx.stroke(); } //画一个白色的圆,用以覆盖 function circle0(ctx, x, y, r, st, end) { ctx.fillStyle = "#ffffff"; ctx.beginPath(); ctx.arc(x, y, r, st, end, true); ctx.fill(); } function circle1(ctx, x, y, r, st, end, w) { ctx.strokeStyle = "gray"; ctx.lineWidth = w; ctx.beginPath(); ctx.arc(x, y, r, st, end, true); ctx.stroke(); } //绘制时钟用的线 function line(ctx, x1, y1, x2, y2, w) { if (w == 1) { ctx.strokeStyle = "red"; } else if (w == 2) { ctx.strokeStyle = "blue"; } else { ctx.strokeStyle = "black"; } ctx.lineWidth = w; ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); } function drawClock() { var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.clearRect(0, 0, c.width, c.height); //绘制一个钟表 var cX = 300; var cY = 200; var radius = 100; //绘制分与秒的刻度 for (var i = 0; i < 60; i++) { circle(ctx, cX, cY, radius, i * 6 * Math.PI / 180, (i + 1) * 6 * Math.PI / 180, 1); } circle0(ctx, cX, cY, radius * 9 / 10, 0, 2 * Math.PI, true); //绘制时刻度 for (var i = 0; i < 12; i++) { circle(ctx, cX, cY, radius, i * 30 * Math.PI / 180, (i + 1) * 30 * Math.PI / 180, 2); } circle0(ctx, cX, cY, radius * 8 / 10, 0, 2 * Math.PI, true); //外围再画一圈 circle1(ctx, cX, cY, radius * 11 / 10, 0, 2 * Math.PI, 1); ctx.save(); ctx.fillStyle = "black"; ctx.font = "10px Arial"; //在钟表的周围画上数字 for (var i = 0; i < 12; i++) { var fX = cX + Math.cos((i + 1) * 5 * 6 * Math.PI / 180 - Math.PI / 2) * radius * 7.5 / 10; var fY = cY + Math.sin((i + 1) * 5 * 6 * Math.PI / 180 - Math.PI / 2) * radius * 7.5 / 10; ctx.fillText((i + 1), fX, fY); } var date = new Date(); var second = date.getSeconds(); var minute = date.getMinutes(); var hour = date.getHours(); hour = hour % 12; //采用12小时制 var secondX = cX + Math.cos(second * 6 * Math.PI / 180 - Math.PI / 2) * radius * 9 / 10; var secondY = cY + Math.sin(second * 6 * Math.PI / 180 - Math.PI / 2) * radius * 9 / 10; var minuteX = cX + Math.cos(minute * 6 * Math.PI / 180 - Math.PI / 2) * radius * 8 / 10; var minuteY = cY + Math.sin(minute * 6 * Math.PI / 180 - Math.PI / 2) * radius * 8 / 10; //小时为了准确起见,应该要加上分的弧度 var hourX = cX + Math.cos(hour * 30 * Math.PI / 180 + (minute * 6 * Math.PI / 180) / 12 - Math.PI / 2) * radius * 6.5 / 10; var hourY = cY + Math.sin(hour * 30 * Math.PI / 180 + (minute * 6 * Math.PI / 180) / 12 - Math.PI / 2) * radius * 6.5 / 10; //画秒针,红色 line(ctx, cX, cY, secondX, secondY, 1); //画分针,蓝色 line(ctx, cX, cY, minuteX, minuteY, 2); //画时针,黑色 line(ctx, cX, cY, hourX, hourY, 3); ctx.fillStyle = "black"; ctx.font = "15px Arial"; ctx.fillText("CurrentTime is : " + date.toLocaleString(), 150, 450); ctx.save(); } window.onload = function () { //循环,1s一次,且要在加载完才可以开始,否则会出现找不到对象的异常 setInterval(drawClock, 1000); } </script>
实例三、绘制太极图
采用Html5+JavaScript在Canvas中绘制旋转的太极图,如下图所示:
具体思路和绘制逻辑,在上图中已有说明,代码如下:
<script type="text/javascript"> //只画边框线,无填充 function bigCircle(ctx,x, y, r, st, end, w,oc) { ctx.lineWidth = w; ctx.beginPath(); ctx.arc(x, y, r, st, end, oc); ctx.closePath(); ctx.stroke(); } //有填充,画小圆,x,y表示大圆的圆心,r表示大圆的半径,w表示线宽,oc表示方向,l表示上下,d表示度数 function smallCircle(ctx, x, y, r, st, end, w, oc, l,d) { var Angle = d * Math.PI / 180; //偏移角用弧度表示 ctx.lineWidth = w; ctx.beginPath(); if (l) { ctx.fillStyle = "black"; ctx.arc(x + (r / 2) * Math.sin(Angle), y - (r / 2) * Math.cos(Angle), r/10, st, end, oc); } else { ctx.fillStyle = "red"; ctx.arc(x - (r / 2) * Math.sin(Angle), y + (r / 2) * Math.cos(Angle), r/10, st, end, oc); } ctx.closePath(); ctx.stroke(); ctx.fill(); } //此函数是画带S形曲线的圆,l表示左右,true表示左,顺时针,false表示右,逆时针 //d表示度数 function halfCircle(ctx, x, y, r, w, l,d) { ctx.lineWidth = w; if (l) { ctx.fillStyle = "black"; } else { ctx.fillStyle = "red"; } ctx.beginPath(); var Angle = d * Math.PI / 180;//偏移角用弧度表示 ctx.arc(x + (r / 2) * Math.sin(Angle), y - (r / 2) * Math.cos(Angle), r / 2, Math.PI / 2 + Angle, Math.PI * 3 / 2 + Angle, true); ctx.arc(x - (r / 2) * Math.sin(Angle), y + (r / 2) * Math.cos(Angle), r / 2, Math.PI*3 / 2 + Angle, Math.PI / 2 + Angle, true); ctx.arc(x, y, r, Math.PI / 2 + Angle, Math.PI * 3 / 2 + Angle, l); //顺时针,逆时针通过参数判断 ctx.closePath(); ctx.stroke(); ctx.fill(); } var num = 0;//表示旋转的度数 function drawTaichi() { var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); var cX = 200; var cY = 200; var radius = 150; ctx.clearRect(0,0,c.width,c.height); //绘制s线 左 halfCircle(ctx, cX, cY, radius, 1, true, num); //右 halfCircle(ctx, cX, cY, radius, 1, false, num); //绘制小圆,上 smallCircle(ctx, cX, cY, radius, 0, Math.PI * 2, 1, true, true, num); //绘制小圆,下 smallCircle(ctx, cX, cY, radius, 0, Math.PI * 2, 1, true, false, num); //绘制外圆 bigCircle(ctx, cX, cY, radius, 0, Math.PI * 2, 2, true); ctx.save(); num++; num = num % 360;//只有360°,所以大于360,就重新开始 } window.onload = function () { setInterval(drawTaichi, 200); } </script>
实例四、绘制五星红旗
Html5+JavaScript 在Canvas上绘制五星红旗,具体思路如下图所示:
绘制思路在上图中已有说明,具体代码如下:
<script type="text/javascript"> //绘制五角星,其中一点垂直向上,相隔的点相连,即可绘制。 function drawStar(ctx,starCenterX,starCenterY,starRadius) { var aX = starCenterX; var aY = starCenterY - starRadius; var bX = starCenterX - Math.cos(18 * Math.PI / 180) * starRadius; var bY = starCenterY - Math.sin(18 * Math.PI / 180) * starRadius; var cX = starCenterX - Math.cos(54 * Math.PI / 180) * starRadius; var cY = starCenterY + Math.sin(54 * Math.PI / 180) * starRadius; var dX = starCenterX + Math.cos(54 * Math.PI / 180) * starRadius; var dY = starCenterY + Math.sin(54 * Math.PI / 180) * starRadius; var eX = starCenterX + Math.cos(18 * Math.PI / 180) * starRadius; var eY = starCenterY - Math.sin(18 * Math.PI / 180) * starRadius; ctx.beginPath(); ctx.fillStyle = "yellow"; ctx.moveTo(aX, aY); ctx.lineTo(cX, cY); ctx.lineTo(eX, eY); ctx.lineTo(bX, bY); ctx.lineTo(dX, dY); ctx.lineTo(aX, aY); ctx.fill(); ctx.closePath(); } window.onload = function () { var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.clearRect(0, 0, c.width, c.height); var width = 300*1.5; var height = 200*1.5; var sX = 50; //其实坐标 var sY = 50; //其实坐标 var step = 10*1.5; //绘制矩形 ctx.beginPath(); ctx.lineWidth = 1; ctx.fillStyle = "red"; ctx.fillRect(sX, sY, width, height); ctx.closePath(); //绘制大五角星 var bigStarCenterX = sX + 5 * step; var bigStarCenterY = sY + 5 * step; var bigStarRadius = (height * 3 / 10) / 2; //外接圆直径为旗高3/10,半径要再除以2 drawStar(ctx, bigStarCenterX, bigStarCenterY, bigStarRadius); //绘制小五角星 var smallStarRadius = (height * 1 / 10) / 2; //外接圆直径为旗高1/10,半径要再除以2 var smallStarCenterX_1 = sX + 10 * step; var smallStarCenterY_1 = sY + 2 * step; drawStar(ctx, smallStarCenterX_1, smallStarCenterY_1, smallStarRadius); var smallStarCenterX_2 = sX + 12 * step; var smallStarCenterY_2 = sY + 4 * step; drawStar(ctx, smallStarCenterX_2, smallStarCenterY_2, smallStarRadius); var smallStarCenterX_3 = sX + 12 * step; var smallStarCenterY_3 = sY + 7 * step; drawStar(ctx, smallStarCenterX_3, smallStarCenterY_3, smallStarRadius); var smallStarCenterX_4 = sX + 10 * step; var smallStarCenterY_4 = sY + 9 * step; drawStar(ctx, smallStarCenterX_4, smallStarCenterY_4, smallStarRadius); }; </script>
备注
赤壁【作者】杜牧【朝代】唐
折戟沉沙铁未销,自将磨洗认前朝。东风不与周郎便,铜雀春深锁二乔。