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);
   }
 }
View Code

 

以上是关于canvas画板基础应用的学习的主要内容,如果未能解决你的问题,请参考以下文章

canvas简易画板。

canvas画板强制横屏画不了

使用Canvas和JavaScript做一个画板

Swift3.0学习实践-一个简单的画板(七色轨迹可撤销可清除带橡皮擦)

用canvas画布画一个画板

canvas小创作 之 实现一个画板(功能:画笔颜色粗细可以任选;橡皮擦功能和清空画板功能)