canvas从入门到动画

1,348 阅读6分钟

学习完canvas,我用canvas画了写动画代码在这里啦canvas动画源码

canvas简介

画布,用来绘制图形, 长久以来,web上的东阿虎都是flash, 比如动画广告都是flash实现的,flash需要插件,漏洞比较多,重量比较大,卡顿和不流畅

canvas是一个轻量级的画布, 可以使用js编程,他是H5标签,不需要任何插件就可以实现广告,游戏,动画,性能也很好,不卡顿,在手机上也能很流畅

hello canvas

简单使用

    // 得到canvas画布
    const canvas = document.getElementById('canvas')
    console.log(canvas)

    // 得到画布的上下文,上下文有两个,2d的上下文和3d的上下文
    let ctx = canvas.getContext("2d")
    // 所有的图像的绘制都是通过ctx属性或者是方法设置的,和canvas标签没有关系了
    // 设置颜色
    ctx.fillStyle = "pink"
    // 绘制矩形
    ctx.fillRect(100,100,100,100)

可见,canvas就是通过js代码在浏览器上画画 注意: 标签的属性只有width 和height,不能通过style属性设置样式

常用的API

  • getContext() 获取上下文
  • fillStyle 填充颜色
  • fillRect(x,y,width,height) 绘制矩形

canvas的像素化

我们使用canvas绘制了一个图形, 一旦绘制成功了, canvas就像素化了他们, canvas没有能力, 从画布上再次得到这个图形,也就是说我们没有能力去修改已经在画布上的内容,就是就是canvas的比较轻量级的原因,flash重的原因之一就是他有可能通过对应的api的到已经上画布的内容然后再绘制 如果我们想要让这个canvas图形移动,必须按照清屏更新渲染的逻辑进行编程,总之就是再重新画\

canvas的动画思想

清屏-更新-渲染

canvas上画布的元素就被像素化了,不能通过style.left 方法进行修改,必须重新渲染 实际上,动画的生成就是相关静态画面连续播放,这个是就是动画的过程,我们把每一次绘制的静态画面叫做一帧,时间的间隔(定时器的间隔)就表示是帧的间隔

我的第一个canvas动画

 // 得到canvas画布
    const canvas = document.getElementById('canvas')
    console.log(canvas)
    // 得到画布的上下文,上下文有两个,2d的上下文和3d的上下文
    let ctx = canvas.getContext("2d")
    // 所有的图像的绘制都是通过ctx属性或者是方法设置的,和canvas标签没有关系了
    // 设置颜色
    ctx.fillStyle = "pink"
    // 绘制矩形
    ctx.fillRect(100,100,200,100)
    // 定义信号量
    let left = 200
   setInterval(function() {
    //  清除画布,0,0代表从什么位置开始清除,600,600代表清除的宽度和高度
      ctx.clearRect(0,0,600,600)
      // 更新信号量
      left++
      // 重新绘制
      ctx.fillRect(left,100,100,100)
    },10)

面向对象思维实现canvas动画

实例走起

 // 得到canvas画布
    const canvas = document.getElementById('canvas')
    let ctx = canvas.getContext("2d")
    console.log(canvas)
    // 定义canvas构造函数
    function Rect (x,y,w,h,color) {
      this.x=x
      this.y=y
      this.w=w
      this.h=h
      this.color = color
    }
    // 更新方法
    Rect.prototype.update = function() {
      this.x++
    }
    // 渲染方法
    Rect.prototype.render = function() {
      ctx.fillStyle = this.color
      ctx.fillRect(this.x,this.y,this.w,this.h)
    }
    // 实例化画布对象
    const r1 = new Rect (100,100,50,50,'red')
   setInterval(function() {
    //  清除画布,0,0代表从什么位置开始清除,600,600代表清除的宽度和高度
      ctx.clearRect(0,0,canvas.width,canvas.height)
      // 更新信号量
      r1.update()
      r1.render()
    
    },10)

canvas的绘制

  1. 绘制矩形:fillStyle fillRect
    // 设置颜色
    ctx.fillStyle = "pink"
    // 绘制矩形
    ctx.fillRect(100,100,200,100)
  1. 绘矩形边框,strokeStyle strokeRect
ctx.strokeStyle = 'red'
ctx.strokeRect(300,100,100,100)
  1. 清除 clearRect
//  清除画布,0,0代表从什么位置开始清除,600,600代表清除的宽度和高度
      ctx.clearRect(0,0,600,600)

绘制路径

绘制路径是为了设置一个不规则的多边形的状态 路径都是闭合的.使用路径进行绘制的时候需要既定的步骤

  1. 需要设置路径的起点 beginPath()
  2. 使用绘制命令画出路径 lineTo()
  3. 封闭路径 closePath()
  4. 填充或者绘制已经封闭路径的形状
   // 得到canvas画布
    const canvas = document.getElementById('canvas')

    let ctx = canvas.getContext("2d")
    // 创建一个路径
    ctx.beginPath()
    // 描述进行路径
    ctx.moveTo(100,100)
    // 描述行进路径
    ctx.lineTo(200,200)
    ctx.lineTo(400,100)
    ctx.lineTo(380,50)
    // 封闭路径
    ctx.closePath()
    // 绘制这个不规则的图形
    ctx.strokeStyle = 'red'
    ctx.stroke()

impicture_20211211_203125.png

绘制圆弧

arc()

arc(x, y, radius, startAngle, endAngle, anticlockwise)

画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。

**注意:arc()函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:*弧度=(Math.PI/180)角度。

ctx.arc(100,100,100,0,1,true);
ctx.stroke()

impicture_20211211_205000.png

ctx.arc(100,100,100,0,1,false);
ctx.stroke()

impicture_20211211_205017.png

ctx.arc(100,100,100,0,2*Math.PI,true);
ctx.stroke()

如果两个参数之间的差值大于7,这个圆弧就是一个圆

impicture_20211211_205048.png

透明度

ctx.globalAlpha : 透明度

线型

线宽

我们可以利用lineWidth 设置先得粗细,属性值必须是数组,默认是1

ctx.lineWeidth = 20

线段末端

lineCap属性决定了每一条线段末端的属性,一共3个属性:分别是butt,round square

连线部分的样式

lineJoin决定了两个线段连接部分的样式的属性 belve miter round

实线和虚线

setLineDash([虚线的长度,两个虚线之间的距离]) lineDashOffset设置虚线的起始偏移量

文本

ctx.font = '30px 微软雅黑' cst,fillText("这个是填充的文字",100,100) textAline = start left center right (基于fillText的x的值)

使用图片

ctx,drawImage(img,100,100,200,120)

资源管理器

我们在开发游戏的时候有一些静态资源是需要求那个球回来的,否则如果直接开始,某些资源没有,会报错,或者空白,比如我们的游戏背景图,如果没有请求回来就加载会有空白的

requestAnimationFrame

requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:

1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。