Canvas

120 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

Canvas

github地址

github.com/boombb12138…

优缺点

优点:Canvas用于绘制2D图形 适合图像密集型的游戏开发

只能通过JS来绘图

Canvas是由像素点构成的图形 放大会使图像模糊

Canvas Grid坐标空间

坐标原点可以通过移动、旋转、缩放改变 后续就基于最新的坐标系

canvas元素默认被网格(坐标空间) 覆盖

绘制矩形:

  1. 矩形方法

    • fillRect(x,y,w,h) 绘填充矩形
    • strokeRect 绘制一个矩形边框
  2. 路径方法

    概念:路径就是点列表 由线段连接

    1. 创建路径起始点beginPath()

    2. 使用绘图命令画出路径

      • moveTo 移动画笔
      • lineTo 移动到 开始点和之前绘制的路径有关,如果路径没有闭合,之前路径结束点就是接下来的开始点
      • arc画圆弧
           // 绘制圆 x,y,半径,起始弧度,结束弧度
                    ctx.arc(30, 30, 20, 0, Math.PI * 2);
      

      ​弧度=(Math.PI/180)*角度 1角度=Math.PI/180个弧度

      旋转360°:Math.PI * 2

    3. 把路径闭合closePath()

    4. 路径生成后需要通过stoke() 描边或fill() 填充来渲染图像

    fill会自动闭合路径

绘制圆弧或者圆

色彩Color

填充颜色 fillStyle = color

描边颜色 strokeStyle = color

属于绘图状态 需要在fill stroke函数前调用

一旦设置了strokeStyle ,strokeStyle 后面没有再设置strokeStyle 就会继续原来的strokeStyle

fillStyle 同理

透明度
  1. 方式1

    strokeStyle 和 fillStyle属性结合rgba:

​ ctx.strokeStyle = "rgba(255,0,0,0.3)";

  1. 方式2

    globalAlpha 属性,这个会影响到canvas所有图形的透明度

    ctx.globalAlpha = 0.8;

线宽

基于路径左右延伸,即路径的两边各绘制线宽的一半

 // 真正的1像素 就是线条刚刚好在像素边界内
            ctx.moveTo(10.5, 10);
            ctx.lineTo(10.5, 100);
            ctx.lineWidth = 1;
            ctx.stroke()

lineCap线条端点的样式

  • butt 截断,默认是 butt。
  • round 圆形
  • square 正方形

lineJoin线条连接处的样式

  • round 圆形
  • bevel 斜角
  • miter 斜槽规,默认是 miter。

绘制文本

2种方法

  1. fillText(指定的文本,x,y) 在(x,y ) 位置,填充指定的文本
  2. strokeText(指定的文本,x,y) 在(x,y ) 位置,绘制文本边框

要设置字体大小和字体类型

            ctx.font = "40px serif";
            ctx.textAlign = "center";//文本对齐选项
            ctx.textBaseline = "middle"//基线对齐选项
            ctx.fillText("Ay", 100, 100)

绘制图片

drawImage方法

drawImage(image, x, y)

其中image可以是image也可以是canvas对象 x和y是其在目标canvas里的起始坐标

先绘制图片再绘制折线

绘画状态

绘画状态可以用save和restore来保存到栈和恢复 没有参数 成对存在

绘画状态:移动旋转缩放 线条的样式(strokeStyle、fillStyle、globalAlpha、lineCap..) 字体样式(font, textAlign, textBaseline ...)

Canvas的形变

  1. 平移
  2. 旋转
  3. 缩放

步骤:

  1. 保存状态 ctx.save();
  2. 形变
  3. 绘制图形
  4. 恢复状态 ctx.restore()
                ctx.save();
                
                ctx.lineWidth = 5
                ctx.lineCap = "round"
                ctx.translate(150, 150) 
                ctx.rotate(
                    Math.PI * 2 / 12 * hours + Math.PI * 2 / 12 / 60 * min + Math.PI * 2 / 12 / 60 / 60 * second
                )
                
                ctx.beginPath();
                ctx.moveTo(0, 0)
                ctx.lineTo(0, -50)
                ctx.stroke()
                ctx.restore()

平移

基于最新的坐标原点 移动坐标

translate移动画布

旋转

rotate(angle):以坐标原点为中心旋转canvas

旋转360°:Math.PI*2

缩放

scale(x, y)会对xy轴放大缩小


     ctx.scale(0.5, 0.5);

动画

对画布上所有的图形一帧一帧重绘

定时重绘:requestAnimationFrame

绘制一帧的步骤

  1. 用clearRect(x,y,w,h) 清空canvas
  2. 保存状态
  3. 修改canvas状态(样式,移动坐标,旋转)
  4. 绘制动画中的一帧
  5. 恢复canvas状态

requestAnimationFrame: 浏览器会下一次重绘之前调用requestAnimationFrame的回调函数

2个案例

solar system.gif

clock.gif