一、入门Canvas

2020-10-09  本文已影响0人  zdxhxh

Canvas

本章学习Canvas以下内容 :

一、创建一个canvas标签

<canvas id="canvasOne" width="500" height="300" >
你的浏览器不支持HTML5
</canvas>

说明 :

  • id : dom元素名称
  • width : 画布宽度
  • height : 画布高度

加载如下的js

import "@s/assets/style/normalize.scss";
import helloworld from '@s/assets/images/helloworld.jpg'
function canvasApp() {
  const theCanvas = document.getElementById("canvasOne");
  // 浏览器检测
  if (!theCanvas || !theCanvas.getContext) {
    return;
  }

  function drawScreen() {
    const context = theCanvas.getContext("2d");
    // 背景
    context.fillStyle = "#000000";
    context.font = "20px Sans-Serif";
    // 文字
    context.textBaseline = "top";
    context.fillText("Hello World!", 195, 80);
    // 图片
    const helloWorldImage = new Image() 
    helloWorldImage.onload = function() {
      context.drawImage(helloWorldImage,160,130)
    }
    helloWorldImage.src = helloworld
    // 边框
    context.strokeStyle = "#000000"
    context.strokeRect(5,5,490,290)
  }

  drawScreen()
}

canvasApp();
image-20200924151239693.png

总结 :

  • Canvas对象可以通过getContext()方法获得HTML52D环境上下文对象,所有操作都需要该对象
  • 上下文对象采用画布左下角为原点(0,0)的笛卡尔坐标系,坐标轴向右,向下为正方向
  • Canvas使用即时模式绘制图像,即每次发生变化后,都会重新绘制,而Flash、Silverlight使用保留模式

二、Canvas公共方法

目前canvas有两个公共方法,一是getContext()、第二个是toDataURL(),这个方法返回当前Canvas对象产生位图的字符串,他就是屏幕的一个快照,通过提供一个不同的MIME类型作为参数,可以返回不同的数据格式,基本的格式是image/png

另外,还有一个公共方法toBlob(),将返回一个引用图像的文件,而不是一个base64编码的字符串。目前,该方法支持度如下 :

image-20200925110637753.png

三、猜字母游戏

程序会随机从a-z抽取一个字母,让玩家按下对应的按键去猜出是哪一个字母。代码如下 :

import "@s/assets/style/normalize.scss";
import helloworld from "@s/assets/images/helloworld.jpg";

class CanvasApp {
  constructor() {
    this.letters = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,s,y,z".split(
      ","
    );
    this.message = "开始进行猜字母游戏,从a-z开始";
    this.today = new Date();
    this.lettersGuess = "";
    this.letterToGuessed = null;
    this.guesses = null;
    this.higherOrLower = "";
    this.gameOver = false;
    this.theCanvas = document.getElementById("canvasOne");
    this.context = this.theCanvas.getContext("2d");
  }
  setup() {
    const letterIndex = Math.floor(Math.random() * this.letters.length);
    this.letterToGuess = this.letters[letterIndex];
    this.guesses = 0;
    this.letterToGuessed = [];
    this.gameOver = false;
    window.addEventListener("keydown", this._eventKeyPressed.bind(this), true);
    document.getElementById('createImageData').addEventListener('click',this._createImageDataPressed.bind(this))
    this.drawScreen();
  }
  _createImageDataPressed() {
    console.log(this.theCanvas.toDataURL())
    let pdfWindow = window.open()
    pdfWindow.document.write(`<img src=${   this.theCanvas.toDataURL()} />`)
    // chrome为了防止CSRF攻击,禁止打开dataURL网址,所以下面这种方式不能用了
    // window.open(
    //   this.theCanvas.toDataURL(),
    //   "canvasImage",
    //   `let=0,top=0,width=${this.theCanvas.width},heigth=${this.theCanvas.height},toolbar=0,resizable=0`
    // );
  }
  _eventKeyPressed(e) {
    if (this.gameOver) return;
    const letterPressed = String.fromCharCode(e.keyCode).toLowerCase();
    this.guesses++;
    this.letterToGuessed.push(letterPressed);
    if (letterPressed == this.letterToGuess) {
      this.gameOver = true;
    } else {
      const letterIndex = this.letters.indexOf(this.letterToGuess);
      const guessIndex = this.letters.indexOf(letterPressed);
      if (guessIndex < 0) {
        this.higherOrLower = "这不是一个字母";
      } else if (guessIndex > letterIndex) {
        this.higherOrLower = "更小";
      } else {
        this.higherOrLower = "更大";
      }
    }
    this.drawScreen();
    console.log(letterPressed);
  }

  drawScreen() {
    const context = this.theCanvas.getContext("2d");
    // 背景
    context.fillStyle = "#ffffaa";
    context.fillRect(0, 0, 500, 300);
    // 边框
    context.strokeStyle = "#000000";
    context.strokeRect(5, 5, 490, 290);

    context.textBaseline = "top";
    // 日期
    context.fillStyle = "#000000";
    context.font = "10px Sans-Serif";
    context.fillText(this.today, 150, 10);
    // 消息
    context.fillStyle = "#ff0000";
    context.font = "14px Sans-Serif";
    context.fillText(this.message, 125, 30);
    // 猜测的次数
    context.fillStyle = "#109910";
    context.font = "16px Sans-Serif";
    context.fillText("Guesses :" + this.guesses, 215, 50);
    // 显示Higher或者Lowere
    context.fillStyle = "#000000";
    context.font = "16px Sans-Serif";
    context.fillText("答案提示: " + this.higherOrLower, 150, 125);
    // 显示猜测过的字母
    context.fillStyle = "#66ccff";
    context.font = "16px Sans-Serif";
    context.fillText(
      "你已猜测过的字母: " + this.letterToGuessed.toString(),
      10,
      260
    );
    if (this.gameOver) {
      context.fillStyle = "#66ccff";
      context.font = "40px sans-serif";
      context.fillText("你猜对了,答案是 : " + this.letterToGuess, 50, 180);
    }
  }
}

new CanvasApp().setup();

三、使用Canvas制造淡入淡出效果

其实上述游戏都可以直接使用HTML来完成,因为静态的图像和文字就是HTML的领域,但是画布具有强大的绘图、着色和基本二维形状变换。

A. 必要属性了解

为了完成这个程序,需要设置一些必要的属性

B. 动画循环

传统的动画实现就是通过不断调用函数不断重新绘制页面出现的,我们需要创建一个函数,每隔一段时间去重复调用它。用于清除画布内容,然后对画布进行重新绘制

function gameLoop(callback) { 
    window.requestAnimation(callback.call(this))
    this.gameLoop()
}

下面为渐变渐出效果

GIF 2020-9-25 14-02-17.gif

下面为源代码

import "@s/assets/style/normalize.scss";
import helloworld from "@s/assets/images/helloworld.jpg";

class CanvasApp {
  constructor() {
    this.theCanvas = document.getElementById("canvasOne");
    this.context = this.theCanvas.getContext("2d");
    this.fadeIn = true;
    this.text = "Hello World";
    this.alpha = 0;
  }
  setup() {
    const helloWorldImage = new Image();
    helloWorldImage.onload = ()=> {
      this.context.drawImage(helloWorldImage,0,0, 720, 300);
    };
    helloWorldImage.src = helloworld;
    this.gameLoop(this.drawScreen);
  }
  gameLoop(callback) {
    window.requestAnimationFrame(this.gameLoop.bind(this, callback));
    callback.call(this);
  }
  drawScreen() {
    this.context.globalAlpha = 1;
    this.context.fillStyle = "#000000";
    this.context.fillRect(0, 0, 720, 300);
    this.context.globalAlpha = 0.25;
    if (this.fadeIn) {
      this.alpha += 0.01;
      if (this.alpha >= 1) {
        this.alpha = 1;
        this.fadeIn = false;
      }
    } else {
      this.alpha -= 0.01;
      if (this.alpha < 0) {
        this.alpha = 0;
        this.fadeIn = true;
      }
    }
    this.context.font = "72px Sans-Serif";
    this.context.textBaseline = "top";
    this.context.globalAlpha = this.alpha;
    this.context.fillStyle = "#ffffff";
    this.context.fillText(this.text, 150, 120);
  }
}

new CanvasApp().setup();

四、Canvas无障碍访问 : 子DOM

什么是无障碍访问 : 无障碍访问即能被残障人士使用的网站,例如语音浏览器、移动电话、手持设备、更多工作在困难环境的用户

Canvas是一个采用即时模式进行位图映射的屏幕区域,因此并不适合实现无障碍访问,在Canvas中,我们并不能通过任何接口访问Canvas里面的元素。所以我们需要创建一些DOM元素放进Canvas标签中,它的作用跟以前所说的JS支持平稳退化是一样的。例如,在单页应用你常看见以下代码,这是为了给不支持Javascript的浏览器一个提示。

<noscript>
    <strong>We're sorry but mobile-mall doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>

同理

<canvas id="canvasOne" width="720" height="300">
    <div id="backup-dom">
        你的浏览器不支持HTML5
    </div>
</canvas>

当然,我们可以触发Canvas某些方法时改变这个DOM元素,这就称为更新后备DOM,当然性能开销是不容小觑的

上一篇下一篇

猜你喜欢

热点阅读