前言

在早期web端的动画、广告、游戏等根本上都是运用Flash来完成的,要在网页上播放Flash需求一堆代码和插件,因而Flash的运用上比较杂乱,还会给开发者带来一堆费事。 自从HTML5供给 Canvas 标签以来它就彻底颠覆了Flash的方位,到现在Flash根本现已淡出了人们的视野。那究竟canvas 强在何处呢?接下来咱们将深入了解一下。

打个广告:
Canvas兄弟/姊妹篇:事例+图解带你一文读懂SVG (3W+) 欢迎点赞收藏 感谢!

Canvas 概述

事例+图解带你一文读懂Canvas(2W+字)

从翻译其实就能很好的了解到 canvas 是用来干什么的。画布!很好理解便是用来画画的。那详细怎么“画”咱们就得看一下详细的 API 文档了。下面是对 canvas 的一些概述:

  • canvas 是一个能够运用脚本(一般为JavaScript)来制作图形的 HTML 元素.
  • Canvas API 供给了一个经过JavaScript 和 HTML的Canvas元从来制作图形的办法。它能够用于动画、游戏画面、数据可视化、图片修改以及实时视频处理等方面。
  • Canvas API 首要聚集于2D图形。而相同运用Canvas元素的 WebGL API 则用于制作硬件加速的2D和3D图形。

Canvas运用

Canvas 最早是由 Apple 引进 WebKit,用于Mac OS X 的 Dashboard,随后被各个浏览器完成。现在除一些过期的浏览器不支撑Canvas元素外,一切的新版别干流浏览器都支撑它。

Canvas元素的学习需求具备一些根本的HTML和JavaScript常识。

根本用法

下面咱们来简单创立一个比如,看看canvas究竟怎么运用。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas 根本运用</title>
</head>
<body>
  <canvas width="200" height="200">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
</body>
</html>

上面代码便是一个根本的运用Canvas标签的比如。能够看到咱们为它设置了宽和高,还在 Canvas标签内部给出一个提示案牍。在这儿需求阐明一下:

  • Canvas标签的默许巨细为:300 x 150 (像素),而这儿咱们设置为了:200 x 200(像素)。
  • Canvas标签中的文字是在不支撑Canvas标签的浏览器中运用的,由于支撑Canvas标签的浏览器会疏忽容器中包含的内容正常烘托Canvas标签,而不支撑Canvas标签的浏览器则相反,浏览器会疏忽容器而显现其间的内容。

能够看一下上面代码在浏览器上的展现款式:

事例+图解带你一文读懂Canvas(2W+字)

烘托上下文

Canvas标签起初仅仅创造了一个固定巨细的画布,它公开了一个或多个烘托上下文,而咱们想对它进行制作就需求找到烘托上下文。

Canvas标签供给了一个办法叫:getContext() ,经过它咱们能够取得烘托上下文和绘画功用。简单写个比如:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas 根本运用</title>
</head>
<body>
  <canvas id="canvas" width="200" height="200">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
    }
  </script>
</body>
</html>

这儿需求留意一点,getContext办法是有一个接收参数,它是绘图上下文的类型,可能的参数有:

  • 2d:建立一个二维烘托上下文。这种状况能够用 CanvasRenderingContext2D()来替换getContext(‘2d’)。
  • webgl(或 experimental-webgl): 创立一个 WebGLRenderingContext 三维烘托上下文目标。只在完成WebGL 版别1(OpenGL ES 2.0)的浏览器上可用。
  • webgl2(或 experimental-webgl2):创立一个 WebGL2RenderingContext 三维烘托上下文目标。只在完成 WebGL 版别2 (OpenGL ES 3.0)的浏览器上可用。
  • bitmaprenderer:创立一个只供给将canvas内容替换为指定ImageBitmap功用的ImageBitmapRenderingContext。

制作形状

在咱们取得制作上下文今后,就能够依据制作上下文开端制作一些根本的形状,比如:直线、三角形、矩形、圆弧和圆。接下来咱们详细完成一下。

直线

制作直线咱们需求了解三个函数:

moveTo(x, y)

设置初始方位,参数为初始方位x和y的坐标点

lineTo(x, y)

制作一条从初始方位到指定方位的直线,参数为指定方位x和y的坐标点

stroke()

经过线条来制作图形概括

接下里咱们运用上面的三个函数来试着制作一条直线,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作直线</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一条从起点(x: 50, y:50)到 另一个点(x: 200, y:200)的直线
      ctx.moveTo(50, 50);
      ctx.lineTo(200, 200);
      ctx.stroke();
    }
  </script>
</body>
</html>

为了展现的作用好一点,这儿我调整了一下画布的巨细:500 x 500,还给画布添加了一个暗影和圆角。得到的直线如图:

事例+图解带你一文读懂Canvas(2W+字)

三角形

知道了怎么制作一条直线,那么制作三角形也就不难了,咱们只需求画三条直线拼在一同便是一个三角形了,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作三角形</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一个三角形
      ctx.moveTo(50, 50);
      ctx.lineTo(200, 200);
      ctx.lineTo(200, 50);
      ctx.lineTo(50, 50);
      ctx.stroke();
    }
  </script>
</body>
</html>

详细作用如下:

事例+图解带你一文读懂Canvas(2W+字)

矩形

知道了三角形的制作,那么矩形的制作是不是也用直线来拼凑呢?答案是否定的,矩形尽管能够用四条直线来拼凑成,但那样太杂乱了,Canvas API 给供给了三种制作矩形的办法:

  • strokeRect(x, y, width, height) 制作一个矩形的边框
  • fillRect(x, y, width, height) 制作一个填充的矩形
  • clearRect(x, y, width, height) 铲除指定矩形区域,让铲除部分彻底通明。

下面咱们顺次看一下他们有什么异同。

strokeRect

strokeRect(x, y, width, height) 是用来制作一个矩形的边框,x和y 是矩形的起点坐标,width和height 是矩形的宽高。举个比如,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作矩形</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一个矩形边框
      ctx.strokeRect(50, 50, 200, 100);
    }
  </script>
</body>
</html>

如下图,strokeRect办法制作的便是一个矩形框:

事例+图解带你一文读懂Canvas(2W+字)

fillRect

fillRect(x, y, width, height) 制作一个填充的矩形,x和y 是矩形的起点坐标,width和height 是矩形的宽高。举个比如,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作矩形</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一个填充矩形
      ctx.fillRect(100, 100, 200, 100);
    }
  </script>
</body>
</html>

如下图,fillRect办法完成的是填充了一个矩形:

事例+图解带你一文读懂Canvas(2W+字)

clearRect

clearRect(x, y, width, height) 铲除指定矩形区域,让铲除部分彻底通明,x和y 是矩形的起点坐标,width和height 是矩形的宽高。这儿需求结合结合另外两种画法来对比一下,才能看出详细的作用,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作矩形</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一个填充矩形
      ctx.fillRect(100, 100, 200, 100);
      ctx.fillRect(50, 50, 200, 100);
      ctx.clearRect(75, 75, 100, 70);
    }
  </script>
</body>
</html>

如下图,中间白色的矩形便是被指定铲除的区域:

事例+图解带你一文读懂Canvas(2W+字)

圆弧和圆

制作圆弧或许圆,运用的办法是:arc(x, y, radius, startAngle, endAngle, anticlockwise)。x和Y为圆心的坐标,radius为半径,startAngle为圆弧或圆的开端方位,endAngle为圆弧或圆的完毕方位,anticlockwise是制作的方向(不写默许为false,从顺时针方向)。

下面画一个半圆弧看看作用,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作圆弧</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段圆弧
      ctx.arc(60, 60, 50, 0, Math.PI, false);
      ctx.stroke();
    }
  </script>
</body>
</html>

作用如下图:

事例+图解带你一文读懂Canvas(2W+字)

这儿需求留意的是:在画弧的时分,arc()函数中角的单位是弧度而不是视点。视点换算为弧度的表达式为:弧度=(Math.PI/180)*视点。

所以想要画一个圆的弧度便是:Math.PI*2,咱们持续画一个圆弧看一下,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作圆弧</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段圆弧
      ctx.arc(60, 60, 50, 0, Math.PI, false);
      ctx.stroke();
      // 制作一个圆弧
      ctx.arc(200, 60, 50, 0, Math.PI*2, false);
      ctx.stroke();
    }
  </script>
</body>
</html>

但作用似乎不想咱们幻想的相同,如下图:

事例+图解带你一文读懂Canvas(2W+字)

如上图所示,先画的半圆弧和后画的圆弧被连在了一同,其实这是由于在咱们每次新建途径的时分都需求敞开和闭合途径,这样不同途径之间才不会彼此搅扰。下面咱们就来介绍一下怎么敞开和闭合途径。

beginPath

新建一条途径,生成之后,图形制作命令被指向到途径上。

closePath

闭合途径之后图形制作命令又重新指向到上下文中。 详细怎么运用这两个函数呢?下面咱们介绍一下,直接上代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作圆弧</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(60, 60, 50, 0, Math.PI, false);
      ctx.stroke();
      ctx.closePath() // 闭合途径
      // 制作一个圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(200, 60, 50, 0, Math.PI*2, false);
      ctx.stroke();
      ctx.closePath() // 闭合途径
    }
  </script>
</body>
</html>

如上代码,咱们为每一条途径都设置了敞开和闭合。那么看一下作用怎么:

事例+图解带你一文读懂Canvas(2W+字)

这儿有一点需求阐明一下,其实在咱们敞开和封闭途径的时分,封闭途径其实并不是必须的,对于新途径其实每次都敞开新途径就ok。

以上其实都是经过stroke办法来做描边,那么假如想填充有没有对应的办法呢?

fill

stroke办法是经过线条来制作图形概括,而fill办法则是经过填充途径的内容区域生成实心的图形。

详细怎么运用举个比如看一下。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 填充</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(60, 60, 50, 0, Math.PI, false);
      ctx.stroke();
      // 制作一个圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(200, 60, 50, 0, Math.PI*2, false);
      ctx.stroke();
      // 填充一个四分之一圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(60, 200, 50, 0, Math.PI/2, false);
      ctx.fill();
      // 填充一个半圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(200, 200, 50, 0, Math.PI, false);
      ctx.fill();
      // 填充一个圆弧
      ctx.beginPath() // 敞开途径
      ctx.arc(350, 200, 50, 0, Math.PI*2, false);
      ctx.fill();
    }
  </script>
</body>
</html>

作用如下图:

事例+图解带你一文读懂Canvas(2W+字)

椭圆

添加椭圆途径。

语法:ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)

  • x、y:椭圆的圆心方位
  • radiusX、radiusY:x轴和y轴的半径
  • rotation:椭圆的旋转视点,以弧度表明
  • startAngle:开端制作点
  • endAngle:完毕制作点
  • anticlockwise:制作的方向(默许顺时针),可选参数。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.beginPath();
      ctx.ellipse(100, 150, 50, 100, 0, 0, 2 * Math.PI);
      ctx.stroke();
      ctx.beginPath();
      ctx.ellipse(400, 150, 50, 100, 0, 0, 2 * Math.PI);
      ctx.stroke();
      ctx.beginPath();
      ctx.ellipse(250, 350, 50, 100, Math.PI/2, 0, 2 * Math.PI); // 旋转90
      ctx.fill();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

贝塞尔曲线

贝塞尔曲线一般用来制作杂乱有规律的图形,在Canvas中也是一个十分有用的途径类型。

二次贝塞尔曲线

语法:quadraticCurveTo(cp1x, cp1y, x, y),其间cp1x和cp1y为一个操控点,x和y为完毕点。

举个比如,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作二次贝塞尔曲线</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段二次贝塞尔曲线
      ctx.moveTo(50, 50);
      ctx.quadraticCurveTo(200, 200, 350, 50);
      // 制作
      ctx.stroke();
    }
  </script>
</body>
</html>

得到的作用图如下:

事例+图解带你一文读懂Canvas(2W+字)

如上图,一段二次贝塞尔曲线是经过一个起点、结尾和完毕点来操控的。下面经过操控点的改动来看一下二次贝塞尔曲线的改动。

把操控点往左移100像素点,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作二次贝塞尔曲线</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段二次贝塞尔曲线
      ctx.beginPath() // 敞开途径
      ctx.moveTo(50, 50);
      ctx.quadraticCurveTo(200, 200, 350, 50);
      // 制作
      ctx.stroke();
      // 制作一段二次贝塞尔曲线
      ctx.beginPath() // 敞开途径
      ctx.moveTo(50, 250);
      ctx.quadraticCurveTo(100, 400, 350, 250);
      // 制作
      ctx.stroke();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

这个其实能够凭借一个网页版的二次贝塞尔曲线调试东西来看一下作用

事例+图解带你一文读懂Canvas(2W+字)

三次贝塞尔曲线

和二次贝塞尔曲线不同的是三次贝塞尔曲线有两个操控点。

语法:ctx.bezierCurveTo(cp1x,cp1y, cp2x,cp2y, x, y),其间cp1x和cp1y为一个操控点,cp2x和cp2y为第二个操控点,x和y为完毕点。

举个比如,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作三次贝塞尔曲线</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段三次贝塞尔曲线
      ctx.beginPath() // 敞开途径
      ctx.moveTo(50, 200);
      ctx.bezierCurveTo(150, 50, 250, 350, 350, 200);
      // 制作
      ctx.stroke();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

这儿也能够凭借一个网页版的三次贝塞尔曲线调试东西来看一下作用:

事例+图解带你一文读懂Canvas(2W+字)

制作款式

在上面的图形制作中都仅仅默许的款式。接下来说一下详细有哪些制作款式。

线条的款式

线条的款式能够经过下面一系列特点来设置。

lineWidth

lineWidth 设置当时绘线的粗细。特点值必须为正数。默许值是 1.0。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作款式</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="300" height="300">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一条宽度为10的直线
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.moveTo(50, 20);
      ctx.lineTo(250, 20);
      ctx.stroke();
      ctx.closePath();
      // 制作一条宽度为20的直线
      ctx.beginPath()
      ctx.lineWidth = 20;
      ctx.moveTo(50, 50);
      ctx.lineTo(250, 50);
      ctx.stroke();
      ctx.closePath();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

lineCap

lineCap 设置线段端点显现的姿态。可选值为:butt,round 和 square。默许是 butt。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作款式</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="300" height="300">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // lineCap 值为 butt
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.lineCap='butt'
      ctx.moveTo(50, 20);
      ctx.lineTo(250, 20);
      ctx.stroke();
      ctx.closePath();
      // lineCap 值为 round
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.lineCap='round'
      ctx.moveTo(50, 50);
      ctx.lineTo(250, 50);
      ctx.stroke();
      ctx.closePath();
      // lineCap 值为 square
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.lineCap='square'
      ctx.moveTo(50, 80);
      ctx.lineTo(250, 80);
      ctx.stroke();
      ctx.closePath();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

lineJoin

lineJoin 该特点能够设置两线段衔接场所显现的姿态。可选值为:round, bevel 和 miter。默许是 miter。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作款式</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="300" height="300">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // lineJoin 值为 miter
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.lineJoin='miter'
      ctx.moveTo(50, 20);
      ctx.lineTo(100, 60);
      ctx.lineTo(150, 20);
      ctx.lineTo(200, 60);
      ctx.lineTo(250, 20);
      ctx.stroke();
      ctx.closePath();
      // lineJoin 值为 round
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.lineJoin='round'
      ctx.moveTo(50, 100);
      ctx.lineTo(100, 140);
      ctx.lineTo(150, 100);
      ctx.lineTo(200, 140);
      ctx.lineTo(250, 100);
      ctx.stroke();
      ctx.closePath();
      // lineJoin 值为 bevel
      ctx.beginPath()
      ctx.lineWidth = 10;
      ctx.lineJoin='bevel'
      ctx.moveTo(50, 180);
      ctx.lineTo(100, 220);
      ctx.lineTo(150, 180);
      ctx.lineTo(200, 220);
      ctx.lineTo(250, 180);
      ctx.stroke();
      ctx.closePath();
    }
  </script>
</body>
</html>

作用为:

事例+图解带你一文读懂Canvas(2W+字)

miterLimit

miterLimit 限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角极点到外角极点的长度。

线段之间夹角比较大时,交点不会太远,但跟着夹角变小,交点间隔会呈指数级增大。

假如交点间隔大于miterLimit值,衔接作用会变成了 lineJoin = bevel 的作用。

举个比如看一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作款式</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="300" height="300">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // miterLimit为定值,视点越大
      ctx.beginPath()
      ctx.lineWidth = 5;
      ctx.lineJoin='miter'
      ctx.miterLimit = 10
      ctx.moveTo(0, 100);
      for (i = 0; i < 30 ; i++) {
        var dy = i % 2 == 0 ? 200 : 100;
        ctx.lineTo(Math.pow(i, 1.5) * 2, dy);
      }
      ctx.stroke();
      ctx.closePath();
    }
  </script>
</body>
</html>

作用为:

事例+图解带你一文读懂Canvas(2W+字)

setLineDash/getLineDash

setLineDash 能够设置当时虚线款式。

getLineDash 则是回来当时虚线设置的款式,长度为非负偶数的数组。

举个比如看一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作虚线</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一条虚线
      ctx.setLineDash([5, 10, 20]);
      console.log(ctx.getLineDash()); // [5, 10, 20, 5, 10, 20]
      ctx.beginPath();
      ctx.moveTo(0,100);
      ctx.lineTo(400, 100);
      ctx.stroke();
      // 再制作一条虚线
      ctx.setLineDash([5, 10, 20, 40]);
      console.log(ctx.getLineDash()); // [5, 10, 20, 40]
      ctx.beginPath();
      ctx.moveTo(0,200);
      ctx.lineTo(400, 200);
      ctx.stroke();
    }
  </script>
</body>
</html>

先看作用再解说,作用如下:

事例+图解带你一文读懂Canvas(2W+字)

首要这儿画两条虚线是想对比一下传参为奇数数组和偶数数组的差异,在咱们设置虚线的时分,假如传参为奇数,例如:ctx.setLineDash([5, 10, 20]),那么 setLineDash 会仿制一份数组补全为偶数,相当于咱们设置的是:ctx.setLineDash([5, 10, 20, 5, 10, 20])。所以这也便是为什么上图中咱们设置的是 [5, 10, 20],成果打印出来是 [5, 10, 20, 5, 10, 20]

lineDashOffset

lineDashOffset 设置虚线款式的开端偏移量。

这儿咱们再画第三条虚线来对比一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作虚线</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一段圆弧
      ctx.setLineDash([5, 10, 20]);
      console.log(ctx.getLineDash()); // [5, 10, 20, 5, 10, 20]
      ctx.beginPath();
      ctx.moveTo(0,100);
      ctx.lineTo(400, 100);
      ctx.stroke();
      ctx.setLineDash([5, 10, 20, 40]);
      console.log(ctx.getLineDash()); // [5, 10, 20, 40]
      ctx.beginPath();
      ctx.moveTo(0,200);
      ctx.lineTo(400, 200);
      ctx.stroke();
      ctx.setLineDash([5, 10, 20, 40]);
      ctx.lineDashOffset = 3;
      ctx.beginPath();
      ctx.moveTo(0,300);
      ctx.lineTo(400, 300);
      ctx.stroke();
    }
  </script>
</body>
</html>

作用为:

事例+图解带你一文读懂Canvas(2W+字)

这儿能够显着看出虚线的总长度没有改动,仅仅开端点向左位移了3像素。

通明度

除了制作实色的图形,还能够制作有通明度的图形。经过设置 globalAlpha 特点或许运用有通明度的款式作为概括或填充都能够完成

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 设置通明度</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 制作一个矩形
      ctx.beginPath();
      // 指定通明度的填充款式
      ctx.fillStyle = "rgba(0, 255, 0, 0.2)";
      ctx.fillRect(10,10,300,100);
      // 制作一个矩形边框
      ctx.beginPath();
      // 指定通明度的描边款式
      ctx.strokeStyle = "rgba(255, 0, 0, 0.7)";
      ctx.strokeRect(10, 90, 100, 300);
      // 制作一个圆
      ctx.beginPath()
      ctx.fillStyle = "rgba(255, 255, 0, 1)";
      // 设置通明度值
      ctx.globalAlpha = 0.5;
      ctx.arc(200, 200, 100, 0, Math.PI*2, true);
      ctx.fill();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

突变

突变分为两种,别离是线性突变和径向突变,在绘图中咱们能够用线性或许径向的突变来填充或描边。

线性突变

语法: createLinearGradient(x1, y1, x2, y2),参数别离为 起点的坐标和结尾的坐标。

在突变的设置中还需求一个办法来添加突变的色彩,语法为:gradient.addColorStop(offset, color),其间color便是色彩,offset 则是色彩的偏移值,只为0到1之间的数。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 突变</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 创立突变
      var gradient1 = ctx.createLinearGradient(10, 10, 400, 10);
      gradient1.addColorStop(0, "#00ff00");
      gradient1.addColorStop(1, "#ff0000");
      var gradient2 = ctx.createLinearGradient(10, 10, 400, 10);
      // 从0.5的方位才开端突变
      gradient2.addColorStop(0.5, "#00ff00");
      gradient2.addColorStop(1, "#ff0000");
      ctx.beginPath()
      ctx.fillStyle = gradient1;
      ctx.fillRect(10, 10, 400, 100);
      ctx.beginPath();
      ctx.fillStyle = gradient2;
      ctx.fillRect(10, 150, 400, 100);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

径向突变

语法:ctx.createRadialGradient(x0, y0, r0, x1, y1, r1),参数别离为开端圆的坐标和半径以及完毕圆的坐标和半径。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 突变</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 创立突变
      // 完毕坐标为点
      var gradient1 = ctx.createRadialGradient(100, 100, 100, 100, 100, 0);
      gradient1.addColorStop(0, "#ff770f");
      gradient1.addColorStop(1, "#ffffff");
      // 完毕坐标为半径30的圆
      var gradient2 = ctx.createRadialGradient(320, 100, 100, 320, 100, 30); 
      gradient2.addColorStop(0, "#ff770f");
      gradient2.addColorStop(1, "#ffffff");
      // 从0.5的方位才开端烘托
      var gradient3 = ctx.createRadialGradient(100, 320, 100, 100, 320, 0); 
      gradient3.addColorStop(0.5, "#ff770f"); 
      gradient3.addColorStop(1, "#ffffff");
      // 开端坐标和完毕坐标不相同
      var gradient4 = ctx.createRadialGradient(320, 320, 100, 250, 250, 0);
      gradient4.addColorStop(0, "#ff770f");
      gradient4.addColorStop(1, "#ffffff");
      ctx.beginPath();
      ctx.fillStyle = gradient1;
      ctx.fillRect(10, 10, 200, 200);
      ctx.beginPath();
      ctx.fillStyle = gradient2;
      ctx.fillRect(220, 10, 200, 200);
      ctx.beginPath();
      ctx.fillStyle = gradient3;
      ctx.fillRect(10, 220, 200, 200);
      ctx.beginPath();
      ctx.fillStyle = gradient4;
      ctx.fillRect(220, 220, 200, 200);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

图画款式

Canvas中想制作图画作用,需求用 createPattern 办法来完成。

语法:createPattern(image, type),参数别离为:Image 参数能够是一个 Image 目标,也能够是一个 canvas 目标,Type 为图画制作的类型,可用的类型别离有:repeat,repeat-x,repeat-y 和 no-repeat。

首要先看一下怎么运用 Image 目标来制作图画。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作图画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 创立一个 image目标
      var img = new Image();
      img.src = "./image.png";
      img.onload = function() {
        // 图片加载完今后
        // 创立图画
        var ptrn = ctx.createPattern(img, 'no-repeat');
        ctx.fillStyle = ptrn;
        ctx.fillRect(0, 0, 500, 500);
      }
    }
  </script>
</body>
</html>

上面是一个用image目标制作的比如,作用如下:

事例+图解带你一文读懂Canvas(2W+字)

从上面的代码咱们能够看出,本来咱们想填充的是一个500*500的长方形,但是由于咱们制作的类型设置为不平铺(no-repeat)所以看到的作用不能让咱们满足,那么咱们别离看看这四个类型别离是什么作用。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作图画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 创立一个 image目标
      var img = new Image();
      img.src = "./image.png";
      img.onload = function() {
        // 图片加载完今后
        // 创立图画
        var ptrn = ctx.createPattern(img, 'repeat');
        ctx.fillStyle = ptrn;
        ctx.fillRect(0, 0, 500, 500);
      }
    }
  </script>
</body>
</html>

设置为平铺(repeat),作用如下:

事例+图解带你一文读懂Canvas(2W+字)
这其实才是咱们想要的作用,那么咱们再看看沿X轴平铺(repeat-x)和沿Y轴平铺(repeat-y)

作用别离是:

事例+图解带你一文读懂Canvas(2W+字)

事例+图解带你一文读懂Canvas(2W+字)

最终看一下怎么运用 canvas 目标来制作图画。 举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作图画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      margin-right: 50px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="200" height="200">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <canvas id="canvas2" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    var canvas2 = document.getElementById('canvas2');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext && canvas2.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ctx2 = canvas2.getContext('2d');
      // 创立一个 canvas目标
      var img = new Image();
      img.src = "./image.png";
      img.onload = function() {
        // 图片加载完今后
        // 创立图画
        var ptrn = ctx.createPattern(img, 'repeat');
        ctx.fillStyle = ptrn;
        ctx.fillRect(0, 0, 200, 200);
        // 用canvas来制作canvas2
        var ptrn2 = ctx2.createPattern(canvas, 'repeat');
        ctx2.fillStyle = ptrn2;
        ctx2.fillRect(0, 0, 500, 500);
      }
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

上面的比如能够看出,canvas2是用canvas1来制作图画的

制作文本

canvas 中仍旧供给了两种办法来烘托文本,一种是描边一种是填充。

strokeText(描边)

语法:ctx.strokeText(text, x, y, maxWidth)参数别离为:

  • text:制作的案牍
  • x、y:文本的开端方位
  • maxWidth:可选参数,最大宽度。需求留意的是当案牍大于最大宽度时不是裁剪或许换行,而是缩小字体

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作文本</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.font = "50px serif"; // 设置案牍巨细和字体
      ctx.strokeText("Canvas 详解", 50, 50);
    }
  </script>
</body>
</html>

看一下作用:

事例+图解带你一文读懂Canvas(2W+字)

fillText(填充)

语法:ctx.fillText(text, x, y, maxWidth)参数别离为:

  • text:制作的案牍
  • x、y:文本的开端方位
  • maxWidth:可选参数,最大宽度。需求留意的是当案牍大于最大宽度时不是裁剪或许换行,而是缩小字体。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作文本</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.font = "50px serif"; // 设置案牍巨细和字体
      ctx.fillText("Canvas 详解", 50, 50);
    }
  </script>
</body>
</html>

文本款式

文本也是能够添加款式的,下面看一下能够设置那些款式

font

用于制作文本的款式。默许的字体是 10px sans-serif。

textAlign

文本对齐的办法。可选值为:left、right、center、start和end。默许值是 start。

direction

文本的方向。可选值为:ltr(文本方向从左向右)、rtl(文本方向从右向左)、inherit(依据状况承继 Canvas元素或许 Document 。)。默许值是 inherit。

需求留意的是 direction 特点会对 textAlign 特点产生影响。假如 direction 特点设置为 ltr,则textAlign特点的 left 和 start 的作用相同,right 和 end 的作用相同,假如 direction 特点设置为 rtl,则 textAlign特点的 left 和 end 的作用相同,right 和 start 的作用相同。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作图画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      margin-right: 50px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="700">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.font = "30px serif"; // 设置案牍巨细和字体
      ctx.direction = "ltr"; // 文本方向从左向右
      ctx.textAlign = "left"; // 左对齐
      ctx.strokeText("Hi Canvas !", 150, 100);
      ctx.direction = "ltr"; // 文本方向从左向右
      ctx.textAlign = "center"; // 右对齐
      ctx.strokeText("Hi Canvas !", 150, 200);
      ctx.direction = "ltr"; // 文本方向从左向右
      ctx.textAlign = "right"; // 右对齐
      ctx.strokeText("Hi Canvas !", 150, 300);
      ctx.direction = "rtl"; // 文本方向从左向右
      ctx.textAlign = "left"; // 左对齐
      ctx.strokeText("Hi Canvas !", 150, 400);
      ctx.direction = "rtl"; // 文本方向从左向右
      ctx.textAlign = "center"; // 右对齐
      ctx.strokeText("Hi Canvas !", 150, 500);
      ctx.direction = "rtl"; // 文本方向从左向右
      ctx.textAlign = "right"; // 右对齐
      ctx.strokeText("Hi Canvas !", 150, 600);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

textBaseline

基线对齐选项,决定文字笔直方向的对齐办法。可选值为:top、hanging、middle、alphabetic、ideographic和bottom。默许值是 alphabetic。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作图画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      margin-right: 50px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.font = "25px serif"; // 设置案牍巨细和字体
      ctx.strokeStyle = 'red';
      const baselines = ['top', 'hanging', 'middle', 'alphabetic', 'ideographic', 'bottom'];
      baselines.forEach(function (baseline, index) {
        ctx.textBaseline = baseline;
        let y = 60 + index * 60;
        ctx.beginPath();
        ctx.moveTo(10, y + 0.5);
        ctx.lineTo(500, y + 0.5);
        ctx.stroke();
        ctx.fillText('Hi Canvas, Welcome to my world! (' + baseline + ')', 10, y);
      });
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

measureText

丈量文本,回来一个 TextMetrics目标。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作图画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      margin-right: 50px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.font = "30px serif"; // 设置案牍巨细和字体
      ctx.beginPath();
      ctx.strokeText("Hi Canvas !", 150, 100);
      var text = ctx.measureText("Hi Canvas !");
      console.log(" ~ 案牍宽度:", text.width)
      ctx.beginPath();
      // 设置了案牍最大宽度
      ctx.strokeText("Hi Canvas !", 150, 200, 100);
      var text1 = ctx.measureText("Hi Canvas !");
      console.log(" ~ 案牍宽度:", text1.width)
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

如上面的作用能够看出,回来的 TextMetrics目标不受最大宽度等外界要素所影响。

那么TextMetrics目标详细有哪些特点?打印看一下:

事例+图解带你一文读懂Canvas(2W+字)

特点解析:

  • TextMetrics.width:依据当时上下文字体,核算内联字符串的宽度。
  • TextMetrics.actualBoundingBoxLeft:从 textAlign 特点确认的对齐点到文本矩形鸿沟左边的间隔,运用 CSS 像素核算;正值表明文本矩形鸿沟左边在该对齐点的左边。
  • TextMetrics.actualBoundingBoxRight:从 textAlign 特点确认的对齐点到文本矩形鸿沟右侧的间隔。
  • TextMetrics.fontBoundingBoxAscent:从 textBaseline 特点标明的水平线到烘托文本的一切字体的矩形最高鸿沟顶部的间隔。
  • TextMetrics.fontBoundingBoxDescent:从 textBaseline 特点标明的水平线到烘托文本的一切字体的矩形鸿沟最底部的间隔。
  • TextMetrics.actualBoundingBoxAscent:从 textBaseline 特点标明的水平线到烘托文本的矩形鸿沟顶部的间隔。
  • TextMetrics.actualBoundingBoxDescent:从 textBaseline 特点标明的水平线到烘托文本的矩形鸿沟底部的间隔。
  • TextMetrics.emHeightAscent:从 textBaseline 特点标明的水平线到线框中 em 方块顶部的间隔。
  • TextMetrics.emHeightDescent:从 textBaseline 特点标明的水平线到线框中 em 方块底部的间隔。
  • TextMetrics.hangingBaseline:从 textBaseline 特点标明的水平线到线框的 hanging 基线的间隔。
  • TextMetrics.alphabeticBaseline:从 textBaseline 特点标明的水平线到线框的 alphabetic 基线的间隔。
  • TextMetrics.ideographicBaseline:从 textBaseline 特点标明的水平线到线框的 ideographic 基线的间隔。

PS:以上一切特点都是运用 CSS 像素核算的,并且都是只读。

暗影

shadowOffsetX、shadowOffsetY

shadowOffsetX 和 shadowOffsetY 用来设定暗影在 X 和 Y 轴的延伸间隔,它们是不受改换矩阵所影响的。负值表明暗影会往上或左延伸,正值则表明会往下或右延伸,它们默许都为 0。

shadowBlur

shadowBlur 用于设定暗影的模糊程度,其数值并不跟像素数量挂钩,也不受改换矩阵的影响,默许为 0。

shadowColor

shadowColor 是标准的 CSS 色彩值,用于设定暗影色彩作用,默许是全通明的黑色。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 暗影</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.font = "50px serif"; // 设置案牍巨细和字体
      ctx.shadowColor = "#cccccc"; //  设置暗影色彩
      ctx.fillStyle = "#ee7934"; //  设置填充色彩
      ctx.shadowOffsetX = 10; // X轴上的暗影
      ctx.shadowOffsetY = 10; // Y轴上的暗影
      ctx.shadowBlur = 5; // 暗影的模糊程度
      ctx.fillText("Hi Canvas !", 100, 50);
      ctx.fillRect(100, 100, 200, 100);
      ctx.shadowOffsetX = -10;
      ctx.shadowOffsetY = -10;
      ctx.shadowBlur = 5;
      ctx.fillText("Hi Canvas !", 100, 300);
      ctx.fillRect(100, 350, 200, 100);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

制作图片

制作图片和上面的图画款式制作根本迥然不同,不同的是所用办法不相同,制作图片是运用 drawImage 办法将它烘托到 canvas 里。

drawImage

这儿咱们首要要说的便是drawImage办法的运用,他的用法有三种,是依据不同的传参完成不同的功用。先看看都有哪些参数:

  • image:制作到上下文的元素。
  • sx、sy:裁剪框的左上角X轴坐标和Y轴坐标。
  • sWidth、sHeight:裁剪框的宽度和高度。
  • dx、dy:制作到上下文的元素,在上下文中左上角的X轴坐标和Y轴坐标。
  • dWidth、dHeight:制作到上下文的元素,在上下文中制作的宽度和高度。假如不阐明,在制作时image宽度和高度不会缩放。

制作

drawImage(image, dx, dy):只要单纯的制作功用,能够制作图片、视频和其他Canvas目标等。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
        var img = new Image();
        img.src = '&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660103116&t=8dd0c641e1e1890fa65ee80dfa428d34';
        img.onload = function(){
          ctx.drawImage(img, 0, 0);
        }
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

如上图所示,咱们能够简单地把一个图片制作到Canvas中。但上面的作用却不是咱们预期中的作用,那么假如咱们想把图片完整的制作到canvas中,咱们就需求其他参数。

缩放

drawImage(image, dx, dy, dWidth, dHeight):在制作的根底上咱们又添加了两个参数,这两个参数能操控制作元素的巨细,整体完成一个缩放的作用。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
        var img = new Image();
        img.src = '&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660103116&t=8dd0c641e1e1890fa65ee80dfa428d34';
        img.onload = function(){
          ctx.drawImage(img, 0, 0, 500, 500);
        }
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

这儿需求阐明一点,在设置dWidth和dHeight两个参数时,不能只设置其间一个,要么都设置要么都不设置。

裁剪

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight):在缩放的根底上又添加了四个参数,整体也是在缩放的根底上添加了裁剪的功用。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var img = new Image();
      img.src = '&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660103116&t=8dd0c641e1e1890fa65ee80dfa428d34';
      img.onload = function(){
        // 在图片的(100,100)方位,裁剪一个300*300巨细的内容,然后缩放到500*500制作到Canvas中(0, 0)的当地
        ctx.drawImage(img, 100, 100, 300, 300, 0, 0, 500, 500);
      }
    }
  </script>
</body>
</html>

上面代码其实便是:在原图片的(100,100)方位,裁剪一个300300巨细的内容,然后再缩放到500500制作到Canvas中(0, 0)的当地。

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

变形

变形算是canvas根底的进阶把,它是一种更强大的办法,能够将原点移动到另一点,还能对网格进行旋转和缩放。

状况的保存和康复

save() 和 restore() 办法是用来保存和康复 canvas 状况的,办法不需求参数。能够理解为便是对canvas 状况的快照进行保存和康复。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.fillStyle = "#cccccc";
      ctx.fillRect(10, 10, 300, 100);
      ctx.save(); // 保存状况
      ctx.fillStyle = "#ee7034";
      ctx.fillRect(10, 150, 300, 100);
      ctx.restore(); // 复原到前次保存的状况
      ctx.fillRect(10, 300, 300, 100);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

如上图作用咱们能够看出,当咱们保存一个状况今后,在咱们康复今后能够持续运用这个状况。

Canvas的状况是存储在栈中的,每次调用save()办法后,当时的状况都会被推送到栈中保存起来。

一个绘画状况包含:

  • 运用的变形:移动、旋转、缩放、strokeStyle、fillStyle、globalAlpha、lineWidth、lineCap、lineJoin、miterLimit、lineDashOffset、shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor、globalCompositeOperation、font、textAlign、textBaseline、direction、imageSmoothingEnabled等。
  • 运用的裁切途径:clipping path

PS:保存和康复能够多次调用, 需求留意的是每一次调用 restore 办法,上一个保存的状况就从栈中弹出,一切设定都康复。

移动、旋转和缩放

  • 移动:translate(x, y) ,x 是左右偏移量,y 是上下偏移量。
  • 旋转:rotate(angle),angle是旋转的视点,它是顺时针旋转,以弧度为单位的值。
  • 缩放:scale(x, y),x 为水平缩放的值,y 为笔直缩放得值。x和y的值小于1则为缩小,大于1则为扩大。默许值为 1。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.fillStyle = '#ee7034';
      ctx.save();
      ctx.save();
      ctx.translate(100, 100); // x和y轴都移动了100
      ctx.fillRect(0, 0, 100, 100);
      ctx.restore();
      ctx.rotate(Math.PI / 4); // 旋转了45度,Math.PI=180度
      ctx.fillRect(0, 0, 100, 100);
      ctx.restore();
      ctx.scale(2, 1);
      ctx.fillRect(100, 300, 100, 100);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

PS:这儿需求留意三点:
save()保存的状况是能够多次保存的,一起保存在栈中的元素遵从的是后进先出的次序;
旋转的中心点始终是 canvas 的原点;
缩放假如是负值的话,则是一个镜像的作用。

transform、setTransform、resetTransform

  • transform(a, b, c, d, e, f)办法能将当时的变形矩阵乘上一个依据本身参数的矩阵;
  • setTransform(a, b, c, d, e, f)办法会将当时变形矩阵重置为单位矩阵,然后用相同的参数调用 transform 办法
  • resetTransform()办法为重置当时变形为单位矩阵。作用等同于调用 setTransform(1, 0, 0, 1, 0, 0)

需求留意的是transform办法和setTransform办法中假如任意一个参数是无限大(Infinity),那么变形矩阵也必须被标记为无限大,不然会抛出异常。

参数阐明:

  • a:水平方向的缩放
  • b:竖直方向的歪斜偏移
  • c:水平方向的歪斜偏移
  • d:竖直方向的缩放
  • e:水平方向的移动
  • f:竖直方向的移动

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      // 
      var sin = Math.sin(Math.PI / 6);
      var cos = Math.cos(Math.PI / 6);
      console.log(" ~ cos, sin", cos, sin)
      ctx.translate(250, 250);
      var c = 0;
      for (var i=0; i <= 12; i++) {
        c = Math.floor(255 / 12 * i);
        ctx.fillStyle = `rgba(${c}, ${c}, ${c})`;
        ctx.beginPath() // 敞开途径
        ctx.arc(60, 100, 100, 0, Math.PI*2, false);
        ctx.fill();
        ctx.transform(cos, sin, -sin, cos, 0, 0);
      }
      // 制作一个矩形
      ctx.fillStyle = "rgba(255, 128, 255, 0.5)";
      ctx.fillRect(0, 50, 100, 100);
      // 上面制作的矩形不是咱们想要的没由于它带上了上面transform的特点
      // 所以需求重置当时变形为单位矩阵
      ctx.resetTransform()
      ctx.fillStyle = "rgba(255, 128, 255, 0.5)";
      ctx.fillRect(0, 50, 100, 100);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

组成与裁剪

组成

组成的图形受限于制作的次序。假如咱们不想受限于制作的次序,那么咱们能够使用 globalCompositeOperation 特点来改动这种状况。

语法:globalCompositeOperation = type,type为组成的类型,详细有哪些类型下面咱们将别离看一下:

source-over

默许值,在现有画布上下文之上制作新图形。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 制作 - drawImage</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      ctx.beginPath();
      ctx.fillStyle = "rgba(255, 0, 0, 1)";
      ctx.fillRect(50, 100, 300, 150);
      ctx.globalCompositeOperation = 'source-over'
      ctx.beginPath();
      ctx.fillStyle = "rgba(0, 255, 0, 1)";
      ctx.fillRect(50, 150, 150, 250);
      ctx.globalCompositeOperation = 'source-over'
      ctx.beginPath();
      ctx.fillStyle = "rgba(0, 0, 255, 1)";
      ctx.fillRect(150, 200, 150, 150);
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

source-in

新图形只在新图形和目标画布堆叠的当地制作。其他的都是通明的。

 ctx.globalCompositeOperation = 'source-in'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

source-out

在不与现有画布内容堆叠的当地制作新图形。

ctx.globalCompositeOperation = 'source-out'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

source-atop

新图形只在与现有画布内容堆叠的当地制作。

ctx.globalCompositeOperation = 'source-atop'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

destination-over

在现有的画布内容后边制作新的图形。

ctx.globalCompositeOperation = 'destination-over'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

destination-in

现有的画布内容保持在新图形和现有画布内容堆叠的方位。其他的都是通明的。

ctx.globalCompositeOperation = 'destination-in'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

destination-out

现有内容保持在新图形不堆叠的当地。

ctx.globalCompositeOperation = 'destination-out'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

destination-atop

现有的画布只保存与新图形堆叠的部分,新的图形是在画布内容后边制作的。

ctx.globalCompositeOperation = 'destination-atop'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

lighter

两个堆叠图形的色彩是经过色彩值相加来确认的。

ctx.globalCompositeOperation = 'lighter'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

copy

只显现新图形。

ctx.globalCompositeOperation = 'copy'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

xor

图画中,那些堆叠和正常制作之外的其他当地是通明的。

ctx.globalCompositeOperation = 'xor'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

multiply

将顶层像素与底层相应像素相乘,成果是一幅更黑暗的图片。

ctx.globalCompositeOperation = 'multiply'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

screen

像素被倒转,相乘,再倒转,成果是一幅更明亮的图片。

ctx.globalCompositeOperation = 'screen'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

overlay

multiply 和 screen 的结合,原本暗的当地更暗,原本亮的当地更亮。

ctx.globalCompositeOperation = 'overlay'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

darken

保存两个图层中最暗的像素。

ctx.globalCompositeOperation = 'darken'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

lighten

保存两个图层中最亮的像素。

ctx.globalCompositeOperation = 'lighten'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

color-dodge

将底层除以顶层的反置。

ctx.globalCompositeOperation = 'color-dodge'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

color-burn

将反置的底层除以顶层,然后将成果反过来。

ctx.globalCompositeOperation = 'color-burn'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

hard-light

屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。

ctx.globalCompositeOperation = 'hard-light'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

soft-light

用顶层减去底层或许相反来得到一个正值。

ctx.globalCompositeOperation = 'soft-light'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

difference

一个柔和版其他强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。

ctx.globalCompositeOperation = 'difference'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

exclusion

和 difference 类似,但对比度较低。

ctx.globalCompositeOperation = 'exclusion'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

hue

保存了底层的亮度(luma)和色度(chroma),一起选用了顶层的色彩(hue)。

ctx.globalCompositeOperation = 'hue'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

saturation

保存底层的亮度(luma)和色彩(hue),一起选用顶层的色度(chroma)。

ctx.globalCompositeOperation = 'saturation'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

color

保存了底层的亮度(luma),一起选用了顶层的色彩 (hue) 和色度 (chroma)。

ctx.globalCompositeOperation = 'color'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

luminosity

保持底层的色彩(hue)和色度(chroma),一起选用顶层的亮度(luma)。

ctx.globalCompositeOperation = 'luminosity'

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

裁剪

裁剪的作用是遮罩,用来隐藏不需求的部分,一切在途径以外的部分都不会在 canvas 上制作出来。

裁剪的作用和 globalCompositeOperation 特点的 source-in 和 source-atop差不多,但也有差异,最重要的差异是裁剪途径不会在 canvas 上制作东西,并且它永久不受新图形的影响。这些特性使得它在特定区域里制作图形时特别好用。

语法:clip() 将当时正在构建的途径转换为当时的裁剪途径。

默许状况下,canvas 有一个与它本身相同大的裁剪途径(也便是没有裁剪作用)。现在能够经过clip()来创立一个裁剪路劲(也就有裁剪作用了)。

clip()

直接举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
        var img = new Image();
        img.src = '&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660103116&t=8dd0c641e1e1890fa65ee80dfa428d34';
        img.onload = function(){
          // 创立圆形裁剪途径
          ctx.arc(250, 250, 200, 0, Math.PI*2, false);
          ctx.clip();
          // 创立完后制作
          ctx.drawImage(img, 0, 0, 500, 500);
        }
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

clip(path, fillRule)

  • path为需求剪切的 Path2D 途径
  • fillRule为判别是在途径内仍是在途径外,允许的值有 nonzero(默许值):非零环绕准则,evenodd:奇偶环绕准则
Path2D

Path2D 用来声明途径,语法:Path2D(),它是一个结构函数,能够创立一个新的 Path2D 目标。
Path2D()有不少办法,先了解一下:

  • addPath():添加一条新途径到对当时途径。
  • closePath():使笔点回来到当时子途径的开端点。它尝试从当时点到开端点制作一条直线。 假如图形现已是封闭的或许只要一个点,那么此函数不会做任何操作。
  • moveTo():将一个新的子途径的开端点移动到 (x,y) 坐标。
  • lineTo():运用直线衔接子途径的结尾到 x, y 坐标。
  • bezierCurveTo():添加一条三次贝赛尔曲线到当时途径。 该办法需求三个点。 第一、第二个点是操控点,第三个点是完毕点。开端点是当时途径的最终一个点,制作贝赛尔曲线前,能够经过调用 moveTo() 进行修改。
  • quadraticCurveTo():添加一条二次贝赛尔曲线到当时途径。
  • arc():添加一条圆弧途径。 圆弧途径的圆心在 (x, y) 方位,半径为 r ,依据anticlockwise (默许为顺时针)指定的方向从 startAngle 开端制作,到 endAngle 完毕。
  • arcTo():依据操控点和半径添加一条圆弧途径,运用直线衔接前一个点。
  • ellipse():添加一条椭圆途径。椭圆的圆心在(x,y)方位,半径别离是radiusX 和 radiusY ,按照anticlockwise (默许顺时针)指定的方向,从 startAngle 开端制作,到 endAngle 完毕。
  • rect():创立一条矩形途径,矩形的起点方位是 (x, y) ,尺寸为 width 和 height。

下面举例看一下怎么运用 Path2D 来创立一个裁剪途径:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
        var img = new Image();
        img.src = '&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1660103116&t=8dd0c641e1e1890fa65ee80dfa428d34';
        img.onload = function(){
          // 创立圆形裁剪途径
          ctx.arc(250, 250, 200, 0, Math.PI*2, false);
          var path1 = new Path2D();
          path1.rect(100, 100, 300, 300);
          ctx.clip(path1);
          // 创立完后制作
          ctx.drawImage(img, 0, 0, 500, 500);
        }
    }
  </script>
</body>
</html>

动画

在 canvas 上制作内容是用 canvas 供给的或许自定义的办法,而一般咱们仅仅在脚本履行完毕后才能看见成果,所以想在 for 循环里面完成动画是不可能的。那么为了完成动画,咱们需求一些能够定时履行重绘的办法。

  • setInterval(function, delay) :定时器,当设定好间隔时间后,function 会定时履行。
  • setTimeout(function, delay):延时器,在设定好的时间之后履行函数
  • requestAnimationFrame(callback):告知浏览器你期望履行一个动画,并在重绘之前,请求浏览器履行一个特定的函数来更新动画。

假如不需求与用户互动,能够运用 setInterval() 办法,它能够定时履行指定的代码。假如需求做游戏,能够运用键盘或许鼠标事情配合上 setTimeout() 办法来完成。经过设置事情监听,能够捕捉用户的交互,并履行相应的动作。

下面咱们选用 window.requestAnimationFrame()来完成一个动画作用。requestAnimationFrame()办法供给了愈加平缓且有效率的办法来履行动画,当系统准备好重绘条件后才会调用制作动画帧。一般每秒钟回调函数履行 60 次,也有可能会被下降,由于一般状况下requestAnimationFrame()办法会遵从 W3C 的建议,浏览器中的回调函数履行次数一般与浏览器屏幕改写次数相匹配。还有为了提高功能和电池寿数,一般 requestAnimationFrame() 办法运行在后台标签页或许隐藏在 里时,requestAnimationFrame() 办法会暂停调用以提升功能和电池寿数。

举个比如看一下:

    <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 太阳系</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var sun = new Image();
      var moon = new Image();
      var earth = new Image();
      function init(){
        sun.src = 'https://www.6hu.cc/files/2022/11/1667935010-7b5926d4739ad79.png_300.png';
        moon.src = '';
        earth.src = '';
        window.requestAnimationFrame(draw);
      }
      function draw() {
        var ctx = document.getElementById('canvas').getContext('2d');
        ctx.globalCompositeOperation = 'destination-over';
        // 清空画布
        ctx.clearRect(0, 0, 500, 500);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
        ctx.strokeStyle = 'rgba(0, 153, 255, 0.4)';
        ctx.save(); // 第一次保存画布状况
        ctx.translate(250, 250); // 把原心移到画布中间
        // 画一个地球
        var time = new Date();
        var earthDeg =  ((2 * Math.PI) / 60) * time.getSeconds() + ((2 * Math.PI) / 60000) * time.getMilliseconds()
        ctx.rotate(earthDeg);
        ctx.translate(200, 0);
        ctx.drawImage(earth, -20, -20, 40, 40);
        // 画一个月亮
        ctx.save(); // 第2次保存画布状况
        var moonDeg = ((2 * Math.PI) / 6) * time.getSeconds() + ((2 * Math.PI) / 6000) * time.getMilliseconds() 
        ctx.rotate(moonDeg);
        ctx.translate(0, 40);
        ctx.drawImage(moon, -7.5, -7.5, 15, 15);
        // 康复状况
        ctx.restore(); 
        ctx.restore();
        // 画一个地球运行的轨迹
        ctx.beginPath();
        ctx.arc(250, 250, 200, 0, Math.PI * 2, false);
        ctx.stroke();
        // 画一个太阳
        ctx.drawImage(sun, 0, 0, 500, 500);
        window.requestAnimationFrame(draw);
      }
      init();
    }
  </script>
</body>
</html>

作用如下:

总结一下制作动画的根本步骤

  • 清空 canvas:除非接下来要画的内容会彻底充溢 canvas(例如背景图),不然需求清空一切。最简单的做法便是用 clearRect 办法。
  • 保存 canvas 状况:假如要改动 canvas 状况的设置(款式,变形之类的),之后又要在每画一帧之时都是原始状况的状况时,需求先保存一下。
  • 制作动画图形(animated shapes)
  • 康复 canvas 状况:假如现已保存了 canvas 的状况,能够先康复它,然后重绘下一帧。

高档动画

高档动画便是在初级动画的根底上加上一些契合物理的运动,这样就能使咱们的动画更生动而不是那么的板滞。
下面咱们一步步来完成一个小球的自由落体的运动。

制作小球

首要咱们先制作一个小球,直接上代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 动画</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ball = {
        x: 100,
        y: 100,
        radius: 25,
        color: 'blue',
        draw: function() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
          ctx.closePath();
          ctx.fillStyle = this.color;
          ctx.fill();
        }
      };
      ball.draw();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

速率

咱们经过给小球添加速率矢量进行移动。这个仍旧用requestAnimationFrame() 办法来完成,在每一帧里面,仍旧用clear 整理掉之前帧里旧的圆形。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ball = {
        x: 100,
        y: 100,
        vx: 1,
        vy: 3,
        radius: 25,
        color: 'blue',
        draw: function() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
          ctx.closePath();
          ctx.fillStyle = this.color;
          ctx.fill();
        }
      };
      function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ball.draw();
        // 添加速率
        ball.x += ball.vx;
        ball.y += ball.vy;
       window.requestAnimationFrame(draw);
      }
      window.requestAnimationFrame(draw);
      ball.draw();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

鸿沟

想让小球反弹那么咱们就需求添加鸿沟

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ball = {
        x: 100,
        y: 100,
        vx: 1,
        vy: 3,
        radius: 25,
        color: 'blue',
        draw: function() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
          ctx.closePath();
          ctx.fillStyle = this.color;
          ctx.fill();
        }
      };
      function draw() {
        ctx.clearRect(0,0, canvas.width, canvas.height);
        ball.draw();
        // 添加速率
        ball.x += ball.vx;
        ball.y += ball.vy;
        // 添加鸿沟
        if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
          ball.vy = -ball.vy;
        }
        if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
          ball.vx = -ball.vx;
        }
       window.requestAnimationFrame(draw);
      }
      window.requestAnimationFrame(draw);
      ball.draw();
    }
  </script>
</body>
</html>

添加完鸿沟的作用如下:

事例+图解带你一文读懂Canvas(2W+字)

加速度

为了让动作更实在,咱们还需求加入加速度的处理。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ball = {
        x: 100,
        y: 100,
        vx: 1,
        vy: 3,
        radius: 25,
        color: 'blue',
        draw: function() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
          ctx.closePath();
          ctx.fillStyle = this.color;
          ctx.fill();
        }
      };
      function draw() {
        ctx.clearRect(0,0, canvas.width, canvas.height);
        ball.draw();
        // 添加加速度
        ball.vy *= .99;
        ball.vy += .25;
        // 添加速率
        ball.x += ball.vx;
        ball.y += ball.vy;
        // 添加鸿沟
        if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
          ball.vy = -ball.vy;
        }
        if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
          ball.vx = -ball.vx;
        }
       window.requestAnimationFrame(draw);
      }
      window.requestAnimationFrame(draw);
      ball.draw();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

拖尾作用

加一个拖尾作用:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 裁剪</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ball = {
        x: 100,
        y: 100,
        vx: 1,
        vy: 3,
        radius: 25,
        color: 'blue',
        draw: function() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
          ctx.closePath();
          ctx.fillStyle = this.color;
          ctx.fill();
        }
      };
      function draw() {
        // ctx.clearRect(0, 0, canvas.width, canvas.height);
        // 用带通明度的矩形代替清空
        ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ball.draw();
        // 添加加速度
        ball.vy *= .995;
        ball.vy += .15;
        // 添加速率
        ball.x += ball.vx;
        ball.y += ball.vy;
        // 添加鸿沟
        if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
          ball.vy = -ball.vy;
        }
        if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
          ball.vx = -ball.vx;
        }
       window.requestAnimationFrame(draw);
      }
      window.requestAnimationFrame(draw);
      ball.draw();
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

运用

最终说一下Canvas的运用。首要是可视化数据的运用,比如说:百度的ECharts、阿里的G2等图表可视化插件。其次是游戏的运用,Canvas 在依据Web的图画显现方面比 Flash 愈加立体、精巧,且Canvas游戏在流通度和跨平台方面更牛。还有图形修改器的运用,比如可视化组态修改东西HT,它彻底依据Canvas制作。未来Photoshop能够依据Canvas在web端100%完成。最终模仿器的运用,模仿器产品能够彻底由 canvas 来完成,视觉作用上愈加逼真模仿实际生活中的东西,进一步优化物联网环境下的运用体会,下降运用者的学习本钱。总是未来Canvas的运用只会越来越普遍,所以具备Canvas这门技术是必不可缺的。

今天呢咱们不可能解说怎么用Canvas开发一个游戏或许怎么完成一个Photoshop。今天只能说一些往常咱们开发中常用的小运用,比如:保存图片、图片灰度或许反相色彩等。

保存图片

保存图片首要运用的办法是:toDataURL()

语法:canvas.toDataURL(‘image/png’),默许设定创立一个 PNG 图片。

canvas.toDataURL(‘image/jpeg’, quality),也能够设定为创立一个 JPG 图片。还能有挑选地供给从 0 到 1 的质量量,1 表明最好质量,0 表明质量最差根本无法区分。

当咱们用toDataURL()办法从画布中生成了一个数据链接后,咱们能够将它用于案例+图解带你一文读懂Canvas(2W+字)元素显现出来,也能够将它放在一个有 download 特点的超链接里用于保存到本地。

举个比如看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 保存图片</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      float: left;
    }
    img {
      width: 500px;
      height: 500px;
      float: right;
    }
    button {
      position: absolute;
      top: 550px;
      left: 50%;
      margin-left: -40px;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <img id="img" src="https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF" />
  <button id="btn">转化为图片且下载</button>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    var Img = document.getElementById('img');
    var Btn = document.getElementById('btn');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var ball = {
        x: 100,
        y: 100,
        vx: 1,
        vy: 3,
        radius: 25,
        color: 'blue',
        draw: function() {
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
          ctx.closePath();
          ctx.fillStyle = this.color;
          ctx.fill();
        }
      };
      function draw() {
        // ctx.clearRect(0, 0, canvas.width, canvas.height);
        // 用带通明度的矩形代替清空
        ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ball.draw();
        // 添加加速度
        ball.vy *= .995;
        ball.vy += .15;
        // 添加速率
        ball.x += ball.vx;
        ball.y += ball.vy;
        // 添加鸿沟
        if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
          ball.vy = -ball.vy;
        }
        if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
          ball.vx = -ball.vx;
        }
       window.requestAnimationFrame(draw);
      }
      window.requestAnimationFrame(draw);
      ball.draw();
    }
    Btn.addEventListener('click', function(){
      // 将canvas转换成base64的url
      var url = canvas.toDataURL("image/png"); 
      // 把Canvas 转化为图片
      Img.src = url;
      // 将base64转换为文件目标
      var arr = url.split(",")
      var mime = arr[0].match(/:(.*?);/)[1] // 此处得到的为文件类型
      var bstr = atob(arr[1]) // 此处将base64解码
      var n = bstr.length
      var u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      // 经过以下办法将以上变量生成文件目标,三个参数别离为文件内容、文件名、文件类型
      var file = new File([u8arr], "filename", { type: mime });
      // 将文件目标经过a标签下载
      var aDom = document.createElement("a"); // 创立一个 a 标签
      aDom.download = file.name; // 设置文件名
      let href = URL.createObjectURL(file); // 将file目标转成 UTF-16 字符串
      aDom.href = href; // 放入href
      document.body.appendChild(aDom); // 将a标签插入 body
      aDom.click(); // 触发 a 标签的点击
      document.body.removeChild(aDom); // 移除刚才插入的 a 标签
      URL.revokeObjectURL(href); // 开释刚才生成的 UTF-16 字符串
    });
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

反相色彩

咱们能够遍历一切像素然后改动他们的数值,然后将被修改的像素数组经过 putImageData() 办法放回到画布中去,以到达反相色彩。invert 函数仅仅是去减掉色彩的最大色值 255,grayscale 函数仅仅是用红绿和蓝的均匀值。也能够用加权均匀,例如 x = 0.299r + 0.587g + 0.114b 这个公式。

直接上比如吧:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 保存图片</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      float: left;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="1000" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <button id="original">Original</button>
  <button id="grayscale">Grayscale</button>
  <button id="inverted">Inverted</button>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    var originalEl = document.getElementById('original');
    var grayscaleEl = document.getElementById('grayscale');
    var invertedEl = document.getElementById('inverted');
    var sepiaEl = document.getElementById('sepia');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var img = new Image();
      img.crossOrigin = 'anonymous';
      img.src = 'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF';
      img.onload = function() {
        ctx.drawImage(img, 0, 0);
      };
      var original = function() {
        ctx.drawImage(img, 0, 0);
      };
      var invert = function() {
        ctx.drawImage(img, 0, 0);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        for (var i = 0; i < data.length; i += 4) {
          data[i]     = 255 - data[i];     // red
          data[i + 1] = 255 - data[i + 1]; // green
          data[i + 2] = 255 - data[i + 2]; // blue
        }
        ctx.putImageData(imageData, 0, 0);
      };
      var grayscale = function() {
        ctx.drawImage(img, 0, 0);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        for (var i = 0; i < data.length; i += 4) {
          var avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
          data[i]     = avg; // red
          data[i + 1] = avg; // green
          data[i + 2] = avg; // blue
        }
        ctx.putImageData(imageData, 0, 0);
      };
      originalEl.addEventListener("click", function(evt) {
        original()
      })
      grayscaleEl.addEventListener("click", function(evt) {
        grayscale()
      })
      invertedEl.addEventListener("click", function(evt) {
        invert()
      })
    }
  </script>
</body>
</html>

作用如下:

事例+图解带你一文读懂Canvas(2W+字)

像素数据

上面的场景中咱们运用了一个办法:getImageData()。该办法会回来一个 ImageData目标,它是画布区域的数据,画布的四个角别离表明为 (left, top)、(left + width, top)、(left, top + height)和(left + width, top + height) 四个点。这四个坐标点被设定为画布坐标空间元素。

语法:ctx.getImageData(left, top, width, height)

接来下咱们再用这个办法做一个拾色器

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 拾色器</title>
  <style>
    /* 给画布添加一个暗影和圆角的款式 */
    canvas {
      box-shadow: 0px 0px 5px #ccc;
      border-radius: 8px;
      float: left;
    }
    div {
      width: 200px;
      height: 500px;
      float: left;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">
    当时浏览器不支撑canvas元素,请晋级或替换浏览器!
  </canvas>
  <div id="hovered"></div>
  <div id="selected"></div>
  <script>
    // 获取 canvas 元素
    var canvas = document.getElementById('canvas');
    var originalEl = document.getElementById('original');
    var grayscaleEl = document.getElementById('grayscale');
    var invertedEl = document.getElementById('inverted');
    var sepiaEl = document.getElementById('sepia');
    // 经过判别getContext办法是否存在来判别浏览器的支撑性
    if(canvas.getContext) {
      // 获取绘图上下文
      var ctx = canvas.getContext('2d');
      var img = new Image();
      img.crossOrigin = 'anonymous';
      img.src = 'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF';
      img.onload = function() {
        ctx.drawImage(img, 0, 0);
        img.style.display = 'none';
      };
      var hoveredColor = document.getElementById('hovered');
      var selectedColor = document.getElementById('selected');
      function pickColor(type, event, destination) {
        var x = event.layerX;
        var y = event.layerY;
        var pixel = ctx.getImageData(x, y, 1, 1);
        var data = pixel.data;
        const rgba = `rgba(${data[0]}, ${data[1]}, ${data[2]}, ${data[3] / 255})`;
        destination.style.background = rgba;
        if(type === 'move') {
          destination.textContent = "划过的色彩为:" + rgba;
        } else {
          destination.textContent = "选中的色彩为:" + rgba;
        }
        return rgba;
      }
      canvas.addEventListener('mousemove', function(event) {
          pickColor('move', event, hoveredColor);
      });
      canvas.addEventListener('click', function(event) {
          pickColor('click', event, selectedColor);
      });
    }
  </script>
</body>
</html>

作用如下:

结语

Canvas在刚推出时主打的优势便是更快的烘托速度,改写了人们对Web页面元素制作速度的形象,但Canvas的优势却不仅限于此。跟着技术的不断更新Canvas的运用也越来越广泛,各种可视化图标、游戏和各种图形化修改器都把Canvas突显的淋漓尽致,特别Google Docs现已宣告将会把HTML迁移到依据Canvas烘托,这一音讯的呈现又把Canvas推上了一个新的高度。

总归Canvas只会越来越重要,它一定会成为每个前端工程师必备的技术之一。所以学会它掌握它让你的技术图谱再添一员猛将。

我正在参加技术社区创作者签约方案招募活动,点击链接报名投稿。