美文网首页
一、入门Canvas

一、入门Canvas

作者: zdxhxh | 来源:发表于2020-10-09 18:45 被阅读0次

    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. 必要属性了解

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

    • context.globalAlpha : 对透明度进行设置,当为0时,文字完全不可见

    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,当然性能开销是不容小觑的

    相关文章

      网友评论

          本文标题:一、入门Canvas

          本文链接:https://www.haomeiwen.com/subject/akfrpktx.html