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 <) {
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 <) {
speed = 4;
} else if (scene.score >= 500000) {
speed = 10;
}
if (count % 40 == 0) {
var index = 0;
if (Math.random()*1000 <) {
index = 0;
}
if (Math.random()*1000 >= 750 && Math.random()*1000 <) {
index = 1;
}
if (Math.random()*1000 >= 800 && Math.random()*1000 <) {
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 <) {
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画板基础应用的学习的更多相关文章
- QML学习笔记(二)-纯qml画图实现canvas画板-鼠标画图
作者: 狐狸家的鱼 Github: 八至 版权声明:如需转载请获取授权和联系作者 用纯qml实现canvas画板功能,用鼠标进行画图,可以画直线,画圆,画矩形,画弧线. 由于canvas画图会有延迟和 ...
- 零基础如何系统学习Java Web
零基础如何系统学习Java Web? 我来给你说一说 你要下决心,我要转行做开发,这样你才能学成. 你要会打字,我公司原来有一个程序员,打字都是两个手一指禅,身为程序员你一指禅怎么写出的代码,半个 ...
- ASP.NET基础之HttpHandler学习
ASP.NET基础之HttpHandler学习 经过前两篇[ASP.NET基础之HttpModule学习]和[ASP.NET基础之HttpContext学习]文章的学习我们对ASP.NET的基础内容有 ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- canvas绘画基础(一):认识canvas画布
html5提供了一个<canvas>标签,结合javascript的canvas api接口可以用来绘制图形和动画.最近工作中涉及到画图的任务,下面来了解一下canvas的基础:canva ...
- C#区块链零基础入门,学习路线图 转
C#区块链零基础入门,学习路线图 一.1分钟短视频<区块链100问>了解区块链基本概念 http://tech.sina.com.cn/zt_d/blockchain_100/ 二.C#区 ...
- (转)ASP.NET基础之HttpHandler学习
原文地址:http://www.cnblogs.com/wujy/archive/2013/08/18/3266009.html 经过前两篇[ASP.NET基础之HttpModule学习]和[ASP. ...
- (转)零基础入门深度学习(6) - 长短时记忆网络(LSTM)
无论即将到来的是大数据时代还是人工智能时代,亦或是传统行业使用人工智能在云上处理大数据的时代,作为一个有理想有追求的程序员,不懂深度学习(Deep Learning)这个超热的技术,会不会感觉马上就o ...
- 【转载】salesforce 零基础开发入门学习(六)简单的数据增删改查页面的构建
salesforce 零基础开发入门学习(六)简单的数据增删改查页面的构建 VisualForce封装了很多的标签用来进行页面设计,本篇主要讲述简单的页面增删改查.使用的内容和设计到前台页面使用的 ...
随机推荐
- Coderfroces 864 D. Make a Permutation!
D. Make a Permutation! Ivan has an array consisting of n elements. Each of the elements is an intege ...
- 笔记本E450机械硬盘数据迁移到固态硬盘
背景: E450机械硬盘使用速度过慢,但E450只有一个SATA位,无法直接使用 “分区助手”迁移. 处理: 1.将固态硬盘通过USB口外接在笔记本上 2.正常打开E450,进入桌面 3.对固态硬盘进 ...
- 紫书 习题 10-19 UVa 10868 (物理动能定理)
这道题看起来很长,而实际上就是考物理 可以用动能定理来算出末速度. 同时注意要特判绳子比桥还长的情况. #include<cstdio> #include<cmath> #de ...
- Transport Tablespace Set(三) ----transport single tablespace
源端字符集与endian查看: SQL> select userenv('language') from dual; USERENV('LANGUAGE') SIMPLIFIED CHINESE ...
- KendoUi中KendoDropDownList控件的使用——三级级联模块的实现
1. 应用需求 在权限系统开发中除了以上数据表关系的设计之外.比較麻烦的地方是级联模块在页面的展示,因为设计中最多是控制到三级,因此三级级联模块的展示.编辑等页面操作是须要解决的问题,这里採用Kend ...
- java8新增特性(一)---Lambda表达式
Lambda表达式也成为闭包,是java语言层次上的改变,Lambda同意把函数作为一个方法的參数(函数作为參数传递进方法中),或者把代码看成数据.函数式程序猿对这一概念非常熟悉. 在JVM平台上有非 ...
- codeforce 571 B Minimization
题意:给出一个序列,经过合适的排序后.使得最小. 做法:将a升序排序后,dp[i][j]:选择i个数量为n/k的集合,选择j个数量为n/k+1的集合的最小值. 举个样例, a={1,2,3,4,5,6 ...
- Raid阵列之简单介绍
1.raid分类 软raid:用软件模拟raid芯片 硬raid:集成的后来添加的 2.raid基本简介 (1)raid是由廉价磁盘冗余阵列发展成为独立磁盘冗余阵列 (2)linux是借助MD(Mui ...
- POJ 2437 贪心+priority_queue
题意: 思路: 贪心 能不覆盖的就不盖 写得很乱 左闭右开的 temp //By SiriusRen #include <queue> #include <cstdio> #i ...
- 下载安装与配置Excel 2013数据挖掘加载项(SQL Server 2012 SP1 + SQLServer2012_DMAddin.msi)
一.系统要求 在安装这个数据挖掘加载项前,你的机器必须要可以支持如下的相关系统设备: (1)操作系统:windows 7 和 windows 8,暂时不支持 windows 10. (2)excel ...