canvas画板基础应用的学习
Posted Asa0728
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canvas画板基础应用的学习相关的知识,希望对你有一定的参考价值。
canvas是html5中的绘图容器,我们可以通过javascript的控制来进行图形的绘制,绘制对象可以是路径、盒、圆、字符等,同时,你也可以通过js给画布添加图像,下面来介绍canvas的各种基本的用法:
1、首先,我们需要在html标签中创建一个canvas标签,并且通过脚本对其进行引入。
<canvas id="myCanvas" width="200" height="100" style="border:1px solid red"> </canvas>
var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d");
在这里,getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。我们对canvas画布的所有操作都是针对ctx而言的。
2、基本图形的绘制方法(线,圆,盒子)
(1)绘制基本的线条
ctx.moveTo(0,0); // 定义画笔开始的起始点坐标 ctx.lineTo(200,100); // 定义画笔结束的结束点坐标 ctx.stroke(); // 执行绘画操作
(2)绘制圆形
ctx.arc(x, y, r, 其实弧度值, 结束弧度值, boolean) boolean为true时逆时针, false为顺时针,默认状态为false
ctx.beginPath(); // 开启绘画的状态 ctx.arc(95,50,40,0,2*Math.PI); // 定义绘制圆形的圆心坐标, 半径等参数 ctx.stroke();
(3)利用canvas进行文本的绘制
绘制实心字体
ctx.font="30px Arial"; //设置字体大小和样式 ctx.fillText("Hello World",10,50); // 设置文本内容, 文本起始点的x, y轴坐标
绘制空心字体
ctx.font="30px Arial"; ctx.strokeText("Hello World",10,50);
3、渐变在canvas中的运用
渐变可以填充在矩形, 圆形, 线条, 文本等等, 各种形状可以自己定义不同的颜色。
以下有两种不同的方式来设置Canvas渐变:
- createLinearGradient(x,y,x1,y1) - 创建线条渐变
- createRadialGradient(x,y,r,x1,y1,r1) - 创建一个径向/圆渐变
当我们使用渐变对象,必须使用两种或两种以上的停止颜色。
addColorStop()方法指定颜色停止,参数使用坐标来描述,可以是0至1.
使用渐变,设置fillStyle或strokeStyle的值为 渐变,然后绘制形状,如矩形,文本,或一条线。
//创建一个线性的渐变
// 创建渐变 var grd=ctx.createLinearGradient(0,0,200,0); grd.addColorStop(0,"red"); grd.addColorStop(1,"white"); // 填充渐变 ctx.fillStyle=grd; ctx.fillRect(10,10,150,80);
// 创建一个径向的渐变
// 创建渐变
var grd=ctx.createRadialGradient(75,50,5,90,60,100); grd.addColorStop(0,"red"); grd.addColorStop(1,"white");
// 填充渐变
ctx.fillStyle=grd; ctx.fillRect(10,10,150,80);
4、外部图片的引入
ctx.drawImage();
html <img src="http://n.sinaimg.cn/translate/20170218/v8d2-fyarrcf4608880.jpg" id="img"/> <canvas height="200" width="200" id="myCanvas"></canvas> js var canvas = document.querySelect("#myCanvas"); var ctx = canvas.getContext("2d"); var img = document.querySelect("#img"); ctx.drawImage(img,10,10);
以上是canvas的最最最基本的一些操作,当然,canvas还可以实现更多强大的功能, 绘制出来更绚丽的图形,通过与js的 结合还可以进行游戏页面的设计及游戏开发
下面是一个用canvas为基本结构绘制的《打灰机✈️》游戏,希望大家多多指
html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style media="screen"> #canvas{ display: block; margin: 0 auto; background: lightgray; border: 1px solid darkgray; } </style> </head> <body> <canvas id="canvas" width="640" height="960"></canvas> <audio src="audio/game_music.mp3" id="gameMusic"></audio> <audio src="audio/bullet.mp3" id="bullet"></audio> <audio src="audio/enemy_out.mp3" id="out"></audio> <audio src="audio/enemy_down.mp3" id="down"></audio> <audio src="audio/game_over.mp3" id="gameOver"></audio> </body> <script src="js/mian.js" charset="utf-8"></script> </html> main.js window.onload = function (){ var scene = new Scene(); // 添加背景 var position = new Position(0, -scene.canvas.height); var size = new Size(scene.canvas.width, scene.canvas.height + 10); var velocity = new Velocity(0, 2); var background = new Spirit(position, size, velocity, \'images/bg_01.jpg\', \'background\'); position = new Position(0, 0); var backgroundRepeat = new Spirit(position, size,velocity, \'images/bg_02.jpg\', \'background\'); scene.addRole(background); scene.addRole(backgroundRepeat); // 添加我方飞机 size = new Size(64, 72); position = new Position((scene.canvas.width - size.width) / 2, scene.canvas.height - size.height); velocity = new Velocity(0, 0); var aircraft = new Spirit(position, size, velocity, \'images/aircraft.png\', \'aircraft\'); scene.addRole(aircraft); // 添加键盘监听事件 document.onkeydown = function (event){ switch (event.keyCode) { case 37: aircraft.velocity.x = -5; break; case 38: aircraft.velocity.y = -5; break; case 39: aircraft.velocity.x = 5; break; case 40: aircraft.velocity.y = 5; break; } console.log(event.keyCode); if (!scene.start && event.keyCode == 13) { window.location.reload(); } }; document.onkeyup = function(){ aircraft.velocity.x = 0; aircraft.velocity.y = 0; } scene.canvas.onclick = function (event){ var x = event.clientX - this.offsetLeft; var y = event.clientY - this.offsetTop; if (!scene.start && x > 220 && x < 420 && y > 520 && y < 580) { window.location.reload(); } } // var requestId = null; function gameStart(){ var gameMusic = document.querySelector(\'#gameMusic\'); gameMusic.loop = \'loop\'; gameMusic.volume = 0.2; gameMusic.play(); // 播放背景音乐 document.querySelector(\'#gameOver\').pause(); requestAnimationFrame(launch); } // 场景加载 var count = 0; var speed = 2; function launch(){ scene.redraw(); if (scene.start) { count++; if (scene.score < 200000) { speed = 2; } else if (scene.score >= 200000 && scene.score < 500000) { speed = 4; } else if (scene.score >= 500000) { speed = 10; } if (count % 40 == 0) { var index = 0; if (Math.random()*1000 < 750) { index = 0; } if (Math.random()*1000 >= 750 && Math.random()*1000 < 900) { index = 1; } if (Math.random()*1000 >= 800 && Math.random()*1000 < 890) { index = 2; document.querySelector(\'#out\').play(); } if (Math.random()*1000 >= 890) { index = 3; } var size1 = new Size(50, 30); var size2 = new Size(70, 90); var size3 = new Size(110, 170); var size4 = new Size(58, 88); var sizes = [size1, size2, size3, size4]; var position = new Position(Math.random() * (scene.canvas.width - sizes[index].width), -sizes[index].height); var velocity = new Velocity(0, speed); if (index == 3) { plane = new Spirit(position, sizes[index], velocity, \'images/ufo1.png\', \'brolly\'); }else { var enemy = \'images/flivver\'+(index + 1)+\'.png\'; var plane = new Spirit(position, sizes[index], velocity, enemy, \'flivver\'); } plane.hp = Math.pow(index,3); switch (index) { case 0: plane.score = 1000; plane.hp = 1; break; case 1: plane.score = 5000; plane.hp = 4; break; case 2: plane.score = 10000; plane.hp = 9; // 大飞机出来时的音效 break; } scene.addRole(plane); } } for (var i = 0; i <= scene.buttles; i++) { if (i < 3) { var speed1 = 20, speed2 = 5; } if (i >= 3 & i < 10) { var speed1 = 10, speed2 = 8; } if (i >= 10) { var speed1 = 4, speed2 = 13; } } switch (scene.buttles) { case 0: bullet (count, aircraft, scene,0, speed1, speed2,0); break; case 1: bullet (count, aircraft, scene,-15, speed1, speed2,0); bullet (count, aircraft, scene,15, speed1, speed2,0); break; case 2: bullet (count, aircraft, scene,0, speed1, speed2,0); bullet (count, aircraft, scene, -15, speed1, speed2,0.2); bullet (count, aircraft, scene,15, speed1, speed2,-0.2); break; case 3: bullet (count, aircraft, scene,7, speed1, speed2,0); bullet (count, aircraft, scene, -7, speed1, speed2,0); bullet (count, aircraft, scene,21, speed1, speed2,-0.2); bullet (count, aircraft, scene,-21, speed1, speed2,0.2); break; case 4: bullet (count, aircraft, scene,10, speed1, speed2,0); bullet (count, aircraft, scene,0, speed1, speed2,0); bullet (count, aircraft, scene, -10, speed1, speed2,0); bullet (count, aircraft, scene,20, speed1, speed2,Math.random() *5); bullet (count, aircraft, scene,-20, speed1, speed2,-Math.random() *5); break; default: bullet (count, aircraft, scene,10, speed1, speed2,0); bullet (count, aircraft, scene,0, speed1, speed2,0); bullet (count, aircraft, scene, -10, speed1, speed2,0); bullet (count, aircraft, scene,20, speed1, speed2, -Math.random() *5); bullet (count, aircraft, scene,-20, speed1, speed2, Math.random() *5); } requestAnimationFrame(launch); } gameStart(); } // 创建对应所需信息 // 设置位置对象 function Position(x, y){ this.x = x; this.y = y; } // 设置尺寸对象 function Size(width, height){ this.width = width; this.height = height; } // 定义增量信息 function Velocity(x, y){ this.x = x; this.y = y; } /****************设置精灵对象******************/ function Spirit(position, size, velocity, chartlet, type){ this.position = position; this.size = size; this.velocity = velocity; this.type = type; this.hp = 0; // 精灵的血量值 this.chartlet = new Image(); this.chartlet.src = chartlet; // 最大位置,用于检测边界 this.maxPosition = new Position(this.position.x + this.size.width, this.position.y + this.size.height); // 根据当前位置计算出下一位置坐标 this.nextPosition = function (){ this.position.x += this.velocity.x; this.position.y += this.velocity.y; this.maxPosition.x = this.position.x + this.size.width; this.maxPosition.y = this.position.y + this.size.height; }; this.previousPosition = function(){ this.position.x -= this.velocity.x; this.position.y -= this.velocity.y; this.maxPosition.x = this.position.x + this.size.width; this.maxPosition.y = this.position.y + this.size.height; }; // 根据精灵的信息进行绘制 this.draw = function (ctx){ ctx.drawImage(this.chartlet, this.position.x, this.position.y, this.size.width, this.size.height); }; } /*******************定义游戏场景类***********************/ function Scene(){ // 获取场景对应的画布和图形上下文信息 this.canvas = document.querySelector(\'#canvas\'); this.ctx = this.canvas.getContext(\'2d\'); this.spirits = []; // 定义spirit数组来保存精灵信息 // this.requestId = null; this.start = true; // 控制游戏是否进行 this.score = 0; this.buttles = 0; // 向数组中添加精灵信息 this.addRole = function (role){ this.spirits.push(role); }; // 定义清空场景的方法 this.clear = function (){ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); }; // 定义重绘地图的方法 this.redraw = function (){ this.clear(); // 定义一个临时数组来保存在画布范围内的精灵 var drawedSpirits = []; for (var i = 0; i < this.spirits.length; i++) { this.spirits[i].nextPosition(); if (this.boundsDetection(this.spirits[i])) { drawedSpirits.push(this.spirits[i]); } else { if (this.spirits[i].type == \'background\') { this.spirits[i].position.y = -this.canvas.height; drawedSpirits.unshift(this.spirits[i]); } if (this.spirits[i].type == \'aircraft\') { this.spirits[i].previousPosition(); drawedSpirits.push(this.spirits[i]); } } } this.spirits = drawedSpirits; // 调用碰撞检测,确定哪些精灵可以被绘制 this.collisionDectection(); for (i = 0; i < this.spirits.length; i++) { if (this.spirits[i].type == \'boom\') { if (this.spirits[i].hp > 0) { this.spirits[i].draw(this.ctx); this.spirits[i].hp -= 0.3; }else { this.spirits.splice(i, 1); i--; } }else { this.spirits[i].draw(this.ctx); } } this.ctx.beginPath(); this.ctx.font = \'45px Chalkduster\'; this.ctx.fillStyle = \'rgba(0,0,0, 0.51)\'; this.ctx.fillText(\'score:\' + this.score, 0, 35); this.ctx.closePath(); // 如果游戏结束则绘制game over if (!this.start) { this.ctx.font = \'80px Chalkduster\'; this.ctx.fillStyle = \'rgb(172, 34, 34)\'; this.ctx.fillText(\'GAME OVER\', 45, 450); this.ctx.rect(220,520,200,60); this.ctx.fillStyle = \'rgba(0,0,0,0.7)\'; this.ctx.fill(); this.ctx.font = \'36px Chalkduster\'; this.ctx.fillStyle = \'white\'; this.ctx.fillText(\'RESTART\', 230, 564); } }; this.boundsDetection = function (role){ switch (role.type) { case \'brolly\': case \'background\': case \'flivver\': if (role.position.y > this.canvas.height) { return false; } else { return true; } break; case \'aircraft\': if (role.position.x < 0 || role.position.y < 0 || role.maxPosition.x > this.canvas.width || role.maxPosition.y > this.canvas.height) { return false; } else { return true; } break; case \'bullet\': if (role.position.y < -role.size.height) { return false; } else { return true; } break; default: return true; } }; // 定义碰撞检测 this.collisionDectection = function (){ var bullets = []; // 场景中所有的子弹 var enemys = []; // 场景中所有的敌机 var brollys = []; // 降落伞的数组 var aircraft = null; // 暂存我方战机 var airctaftindex = 0; // 暂存我方战机在精灵数组中的下标 for (var i = 0; i < this.spirits.length; i++) { switch (this.spirits[i].type) { case \'bullet\': bullets.push(this.spirits[i]); break; case \'flivver\': enemys.push(this.spirits[i]); break; case \'aircraft\': aircraft = this.spirits[i]; aircraftIndex = i; break; case \'brolly\': brollys.push(this.spirits[i]); break; default: } } for (i = 0; i < bullets.length; i++) { for (var j = 0; j < enemys.length; j++) { if (bullets[i].position.x > enemys[j].position.x && bullets[i].position.x < enemys[j].maxPosition.x && bullets[i].position.y > enemys[j].position.y && bullets[i].position.y < enemys[j].maxPosition.y) { var bulletsIndex = this.spirits.indexOf(bullets[i]); this.spirits.splice(bulletsIndex, 1); if(--enemys[j].hp <= 0) { this.score += enemys[j].score; var enemyIndex = this.spirits.indexOf(enemys[j]); this.spirits.splice(enemyIndex, 1); } // 创建子弹爆炸精灵 var size = new Size(41, 39); var position = new Position(bullets[i].position.x - size.width / 2, bullets[i].position.y - size.height / 2); var velocity = new Velocity(0, 0); var boom = new Spirit(position, size, velocity, \'images/boo1.png\', \'boom\'); boom.hp = 2; this.spirits.push(boom); // 子弹打到飞机 document.querySelector(\'#down\').play(); break; } } } // 进行我方战机跟敌机的碰撞检测 for (i = 0; i < enemys.length; i++) { var centerx = enemys[i].position.x + enemys[i].size.width / 2; var centery = enemys[i].position.y + enemys[i].size.height / 2; if (centerx > (aircraft.position.x - enemys[i].size.width / 2 + 10) && centerx < (aircraft.maxPosition.x + enemys[i].size.width / 2 - 10) && centery > (aircraft.position.y - enemys[i].size.height / 2 + 10) && centery < (aircraft.maxPosition.y + enemys[i].size.height / 2 - 10)) { this.start = false; this.spirits = [this.spirits[0], this.spirits[1]]; document.querySelector(\'#gameMusic\').pause(); document.querySelector(\'#gameOver\').play(); // document.querySelector(\'#gameOver\').loop = \'loop\'; break; } } // 进行装备包的碰撞检测 for (i = 0; i < brollys.length; i++) { var centerX = brollys[i].position.x + brollys[i].size.width / 2; var centerY = brollys[i].position.y + brollys[i].size.height / 2; if (centerX > (aircraft.position.x - brollys[i].size.width / 2 + 10) && centerX < (aircraft.maxPosition.x + brollys[i].size.width / 2 - 10) && centerY > (aircraft.position.y - brollys[i].size.height / 2 + 10) && centerY < (aircraft.maxPosition.y + brollys[i].size.height / 2 - 10)) { this.spirits.splice(this.spirits.indexOf(brollys[i]),1); this.buttles++; break; } } }; } // 构建 制造子弹的函数 function bullet ( count, aircraft, scene, left, speed1, speed2, speed3){ if (count % speed1 === 0) { var size = new Size(7, 17); var position = new Position(aircraft.position.x + aircraft.size.width / 2 - size.width / 2 - left, aircraft.position.y - size.height); var velocity = new Velocity(speed3, -speed2); var bullet = new Spirit(position, size, velocity, \'images/bullet.png\', \'bullet\'); document.querySelector(\'#bullet\').play(); document.querySelector(\'#bullet\').volume = 0.2; scene.addRole(bullet); } }
以上是关于canvas画板基础应用的学习的主要内容,如果未能解决你的问题,请参考以下文章