五、 Canvas 入门案例
1. canvas 圆形绘制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas圆形绘制</title> <style> * { margin: 0; } #canvas { display: block; margin: 50px auto; background-color: #ffffff; } </style> </head> <body bgcolor="black"> <canvas id="canvas" width="500" height="500"></canvas> </body> <script> var cxt = canvas.getContext('2d');//画笔 var color = cxt.createLinearGradient(0, 200, 0, 300); color.addColorStop(0, 'pink'); color.addColorStop(1, 'red'); cxt.shadowColor = 'red'; cxt.shadowOffsetX = 1; cxt.shadowOffsetY = 1; cxt.shadowBlur = 50;//模糊度 cxt.save();//保存路径 cxt.fillStyle = color;//填充颜色 cxt.beginPath();//开始路径 cxt.arc(250, 250, 50, 0, Math.PI * 2, false);//绘制圆(x,y,r,0deg,360deg,false/true); cxt.closePath();//闭合路径 cxt.fill();//填充方法 cxt.restore();//释放路径 </script> </html>
2. canvas 线条绘制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas线条绘制</title> <style> *{ margin: 0; } #canvas{ display: block; margin: 50px auto; background-color: #ffffff; } </style> </head> <body bgcolor="black"> <canvas id="canvas" width="500" height="500"></canvas> </body> <script> var cxt = canvas.getContext('2d');//画笔 //线条颜色渐变 var color = cxt.createLinearGradient(100,200,300,200); color.addColorStop(0,'yellow'); color.addColorStop(1,'red'); cxt.save();//保存路径 cxt.strokeStyle = color;//线条颜色 cxt.lineWidth = 1;//线条宽度 cxt.beginPath();//开始路径 cxt.moveTo(100,200);//起点坐标 绘制线; cxt.lineTo(300,200);//终点坐标 绘制线; cxt.closePath();//闭合路径 cxt.stroke();//线条颜色方法 cxt.restore();//释放路径 </script> </html>
3. canvas 矩形绘制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas矩形绘制</title> <style> * { margin: 0; } #canvas { display: block; margin: 50px auto; background-color: #ffffff; } </style> </head> <body bgcolor="black"> <canvas id="canvas" width="500" height="500"></canvas> </body> <script> var cxt = canvas.getContext('2d');//画笔 var color = cxt.createLinearGradient(0, 200, 0, 300); color.addColorStop(0, 'pink'); color.addColorStop(1, 'red'); cxt.shadowColor = 'red'; cxt.shadowOffsetX = 1; cxt.shadowOffsetY = 1; cxt.shadowBlur = 50;//模糊度 cxt.save();//保存路径 cxt.fillStyle = color;//填充颜色 cxt.beginPath();//开始路径 cxt.rect(200,200,6,160);//绘制矩形(x,y,w,h); cxt.closePath();//闭合路径 cxt.fill();//填充方法 cxt.restore();//释放路径 </script> </html>
4. 粒子连线
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>粒子连线</title> </head> <body> <canvas id="canvas" style="background-color: black"></canvas> </body> <script> function Star() { this.cxt = canvas.getContext('2d'); console.log(this.cxt); this.CircleNum = 200;//粒子个数 this.data = [];//存储粒子的数据 } Star.prototype = { //初始化 init: function () { canvas.width = window.innerWidth; canvas.height = window.innerHeight; this.cW = canvas.width; this.cH = canvas.height; for (var i = 0; i < this.CircleNum; i++) { this.data[i] = { //粒子位置 x: Math.random() * this.cW, y: Math.random() * this.cH, //粒子速度增量 sX: -0.3 + Math.random() * 0.6, sY: -0.3 + Math.random() * 0.6, }; // this.drawCircle(this.data[i].x, this.data[i].y); } }, //绘制粒子 drawCircle: function (x, y) { var cxt = this.cxt; cxt.save();//保存路径 cxt.fillStyle = 'pink';//填充颜色 cxt.beginPath();//开始路径 cxt.arc(x, y, 1, 0, Math.PI * 2, false);//绘制圆(x,y,r,0deg,360deg,false/true); cxt.closePath();//闭合路径 cxt.fill();//填充方法 cxt.restore();//释放路径 }, //移动粒子以及粒子连线 moveCircle: function () { var self = this; var cxt = self.cxt; var cW = self.cW; var cH = self.cH; cxt.clearRect(0, 0, cW, cH);//先清空画布 for (var i = 0; i < self.CircleNum; i++) { self.data[i].x += self.data[i].sX; self.data[i].y += self.data[i].sY; //边界的碰撞检测 if (self.data[i].x > cW || self.data[i].x < 0) self.data[i].sX = -self.data[i].sX; if (self.data[i].y > cH || self.data[i].y < 0) self.data[i].sY = -self.data[i].sY; self.drawCircle(self.data[i].x, self.data[i].y); //判断粒子连线:连成三角形,勾股定理 for (var j = 0; j < self.CircleNum; j++) {//下一个点 if (Math.pow(self.data[i].x - self.data[j].x, 2) + Math.pow(self.data[i].y - self.data[j].y, 2) <= 60 * 60) { self.drawLine(self.data[i].x, self.data[i].y, self.data[j].x, self.data[j].y); } } //鼠标移入进行连线 var mouse = document.getElementById("canvas"); mouse.onmousemove = function (event) {//获取鼠标坐标 var e = event || window.event; self.mouseX = Math.floor(e.clientX);//e.pageX/pageY self.mouseY = Math.floor(e.clientY); }; //console.log(self.mouseX+":"+self.mouseY ); if (Math.pow(self.data[i].x - self.mouseX, 2) + Math.pow(self.data[i].y - self.mouseY, 2) <= 100 * 100) { self.drawLine(self.data[i].x, self.data[i].y, self.mouseX, self.mouseY); } } }, //绘制线条 drawLine: function (x1, y1, x2, y2) { var cxt = this.cxt; //线条颜色渐变 var color = cxt.createLinearGradient(x1, y1, x2, y2); color.addColorStop(0, '#0ff'); color.addColorStop(1, '#06f'); cxt.save();//保存路径 cxt.strokeStyle = color;//线条颜色 cxt.globalCompositeOperation = "lighter"; cxt.lineWidth = .1;//线条宽度 cxt.beginPath();//开始路径 cxt.moveTo(x1, y1);//起点坐标 绘制线; cxt.lineTo(x2, y2);//终点坐标 绘制线; cxt.closePath();//闭合路径 cxt.stroke();//线条颜色方法 cxt.restore();//释放路径 } }; var star = new Star();//实例化对象 star.init(); /* setInterval(function () { star.moveCircle(); }, 6);*/ function render() { star.moveCircle(); requestAnimationFrame(render);//请求帧动画, 回调稳步执行 } render(); </script> </html>
5. 鼠标滑动冒泡
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="KeyWords" content=""> <meta name="Description" content=""> <title>canvas鼠标滑动气泡</title> </head> <body> <canvas id="canvas" style="background-color: black"></canvas> </body> <script> (function () { function Bubble(x,y) { this.cxt = canvas.getContext('2d'); this.x = x; this.y = y; this.r = Math.random() * 90; this.color = "#"+Math.floor(Math.random()*1000); this.sX = -2 + Math.random() * 4; this.sY = -2 + Math.random() * 4; } Bubble.prototype = { //初始化canvas init: function () { canvas.width = window.innerWidth; canvas.height = window.innerHeight; this.cW = canvas.width; this.cH = canvas.height; }, //画气泡 drawBubble: function () { var cxt = this.cxt; cxt.save(); cxt.fillStyle = this.color; cxt.globalCompositeOperation = "lighter";//颜色叠加方案xor cxt.beginPath(); cxt.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);//false逆时针 cxt.closePath(); cxt.fill(); cxt.restore(); }, //鼠标滑动气泡 moveBubble: function () { var self = this; self.x +=self.sX; self.y +=self.sY; self.r *=0.96; }, //按键恢复气泡的大小 change:function () { this.r = 90; } }; var bubbleList = [];//储存气泡的容器 var bubble = new Bubble(); bubble.init(); canvas.addEventListener("mousemove", function (e) { bubbleList.push(new Bubble(e.clientX, e.clientY)); }); function render() { bubble.cxt.clearRect(0,0,bubble.cW,bubble.cH); bubbleList.forEach(function (ball) {//绘制操作 ball.drawBubble(); ball.moveBubble(); }); for (var i in bubbleList){//释放空间,维护操作 if (bubbleList[i].r == 0.001) bubbleList.splice(i,1); } requestAnimationFrame(render); } render(); window.addEventListener("keydown",function (e) {//按键还原气泡 if (e.keyCode =='32'){ bubbleList.forEach(function (ball) { ball.change(); }); } }); })(); </script> </html>
6. 彩虹雨
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Canvas雨滴</title> <style> * { padding: 0; margin: 0; } </style> </head> <style> </style> <body> <canvas id="canvas" style="background-color: black"> <audio src="下雨声.mp3" controls autoplay="autoplay" loop="loop"></audio> </canvas> </body> <script> (function () { function Rain() { this.cxt = canvas.getContext('2d'); this.rainData = { x: random(0, window.innerWidth), y: random(-1, 0), vX: random(8, 16), vY: random(16, 32), r: random(2, 6), h: -60, }; this.color = { red: Math.floor(random(0, 255)), green: Math.floor(random(0, 255)), black: Math.floor(random(0, 255)), }; } function random(min, max) { return min + Math.random() * (max - min); } Rain.prototype = { //初始化 init: function () { canvas.width = window.innerWidth; canvas.height = window.innerHeight; this.cW = canvas.width; this.cH = canvas.height; this.cloudNum = 66; this.cloudData = []; for (var i = 0; i < this.cloudNum; i++) this.cloudData[i] = { x: random(-100, 1300), y: random(360, 600), r: random(20, 60), }; }, //空中雨滴 drawRain: function () { var cxt = this.cxt; var c = this.color; var data = this.rainData; var color = cxt.createLinearGradient(data.x, data.y, data.x, data.y + data.h); color.addColorStop(0, "rgba(" + c.red + "," + c.green + "," + c.black + "," + "1)"); color.addColorStop(1, "rgba(" + c.red + "," + c.green + "," + c.black + "," + "0.1)"); cxt.save(); cxt.fillStyle = color; cxt.beginPath(); cxt.rect(data.x, data.y, 1, data.h); cxt.closePath(); cxt.fill(); cxt.restore(); }, moveRain: function () { var flag, inX, inY, lastX; for (var i = 0; i < rain.cloudNum; i++) { //碰撞检测 if (Math.pow(rain.cloudData[i].x - this.rainData.x, 2) + Math.pow(rain.cloudData[i].y - this.rainData.y, 2) <= rain.cloudData[i].r * rain.cloudData[i].r) { flag = true; inX = this.rainData.x; inY = this.rainData.y; break; } else { flag = false; } } //console.log(flag); if (flag) { this.rainData.h = 0; lastX = rain.cloudData[i].x; this.rainData.y -= this.rainData.vY * random(0, 6); this.rainData.x += (this.rainData.x > lastX ? this.rainData.vX : -this.rainData.vX); this.drawCircle(inX, inY - this.rainData.r, this.rainData.r, this.color.red, this.color.green, this.color.black); } else { if (this.rainData.h > -60) this.rainData.h -= 6; this.rainData.y += this.rainData.vY; } }, //云层雨滴 drawCircle: function (x, y, r, red, green, black) { var cxt = this.cxt; cxt.save(); cxt.fillStyle = "rgb(" + red + "," + green + "," + black + ")"; cxt.shadowColor = "rgb(" + red + "," + green + "," + black + ")"; cxt.shadowBlur = 30; cxt.globalCompositeOperation = 'lighter'; cxt.beginPath(); cxt.arc(x, y, r, 0, Math.PI * 2, false); cxt.closePath(); cxt.fill(); cxt.restore(); }, //云层 drawCloud: function (x, y, r) { this.drawCircle(x, y, r, 15, 15, 15); }, //云层移动与碰撞检测 moveCloud: function () { var data = this.cloudData; for (var i = 0; i < this.cloudNum; i++) { data[i].x += 0.8; if (data[i].x - data[i].r > this.cW) data[i].x = -data[i].r; data[i].r *= random(0.9999, 1); if (data[i].r < 20 || data[i].r > 60) data[i].r = random(20, 60); this.drawCloud(data[i].x, data[i].y, data[i].r); } }, }; var rain = new Rain(); rain.init(); var rainArr = []; function produce() { for (var i = 0; i < 2; i++) rainArr.push(new Rain()); } function render() { rain.cxt.clearRect(0, 0, rain.cW, rain.cH); produce(); rainArr.forEach(function (rainer) { rainer.drawRain(); rainer.moveRain(); }); rain.drawRain(); rain.moveCloud(); //回收机制 for (var i in rainArr) { if (rainArr[i].rainData.y > rain.cH || rainArr[i].rainData.x > rain.cW) rainArr.splice(i, 1); } //console.log(rainArr.length); requestAnimationFrame(render); } render(); } )(); </script> </html>