第154天:canvas基础(一)

一、canvas简介

​ <canvas> 是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。

​ 它最初由苹果内部使用自己MacOS X WebKit推出,供应用程序使用像仪表盘的构件和 Safari 浏览器使用。 后来,有人通过Gecko内核的浏览器 (尤其是MozillaFirefox),OperaChrome和超文本网络应用技术工作组建议为下一代的网络技术使用该元素。

​ Canvas是由HTML代码配合高度宽度属性而定义出的可绘制区域。JavaScript代码可以访问该区域,类似于其他通用的二维API,通过一套完整的绘图函数来动态生成图形。

Mozilla 程序从 Gecko 1.8 (Firefox 1.5)开始支持 <canvas>, Internet Explorer 从IE9开始<canvas> 。ChromeOpera 9+ 也支持<canvas>

二、Canvas基本使用

2.1 <canvas>元素

<canvas id="tutorial" width="300" height="300"></canvas>

<canvas>看起来和<img>标签一样,只是 <canvas> 只有两个可选的属性 widthheight 属性,而没有 src、alt 属性。

​ 如果不给<canvas>设置widht、height属性时,则默认 width为300、height为150,单位都是px。也可以使用css属性来设置宽高,但是如宽高属性和初始比例不一致,他会出现扭曲。所以,建议永远不要使用css属性来设置<canvas>的宽高。

1、替换内容

​ 由于某些较老的浏览器(尤其是IE9之前的IE浏览器)或者浏览器不支持HTML元素<canvas>,在这些浏览器上你应该总是能展示替代内容。

​ 支持<canvas>的浏览器会只渲染<canvas>标签,而忽略其中的替代内容。不支持 <canvas> 的浏览器则 会直接渲染替代内容。

(1)用文本替换:

1 <canvas>
2     你的浏览器不支持canvas,请升级你的浏览器
3 </canvas>

(2)用 <img> 替换:

1 <canvas>
2     <img src="./美女.jpg" alt=""> 
3 </canvas>

结束标签</canvas>不可省

与 <img>元素不同,<canvas>元素需要结束标签(</canvas>)。如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来。

2.2 渲染上下文(Thre Rending Context)

​ <canvas>会创建一个固定大小的画布,会公开一个或多个 渲染上下文(画笔),使用 渲染上下文来绘制和处理要展示的内容。

​ 我们重点研究 2D渲染上下文。 其他的上下文我们暂不研究,比如, WebGL使用了基于OpenGL ES的3D上下文 (“experimental-webgl”) 。

1 var canvas = document.getElementById('tutorial');
2  //获得 2d 上下文对象
3 3var ctx = canvas.getContext('2d');

2.3 检测支持性

1 var canvas = document.getElementById('tutorial');
2 
3 if (canvas.getContext){
4   var ctx = canvas.getContext('2d');
5   // drawing code here
6 } else {
7   // canvas-unsupported code here
8 }

2.4 代码模板

 1 <html>
 2 <head>
 3     <title>Canvas tutorial</title>
 4     <style type="text/css">
 5         canvas {
 6             border: 1px solid black;
 7         }
 8     </style>
 9 </head>
10 <canvas id="tutorial" width="300" height="300"></canvas>
11 </body>
12 <script type="text/javascript">
13     function draw(){
14         var canvas = document.getElementById('tutorial');
15         if(!canvas.getContext) return;
16         var ctx = canvas.getContext("2d");
17         //开始代码
18 
19     }
20     draw();
21 </script>
22 </html>

2.5 一个简单的例子

绘制两个长方形。

<html>
<head>
    <title>Canvas tutorial</title>
    <style type="text/css">
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<canvas id="tutorial" width="300" height="300"></canvas>
</body>
<script type="text/javascript">
    function draw(){
        var canvas = document.getElementById('tutorial');
        if(!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "rgb(200,0,0)";
        //绘制矩形
        ctx.fillRect (10, 10, 55, 50);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 55, 50);
    }
    draw();
</script>
</html>

三、绘制形状

3.1 栅格(grid)和坐标空间

​ 如下图所示,canvas元素默认被网格所覆盖。通常来说网格中的一个单元相当于canvas元素中的一像素。栅格的起点为左上角(坐标为(0,0))。所有元素的位置都相对于原点来定位。所以图中蓝色方形左上角的坐标为距离左边(X轴)x像素,距离上边(Y轴)y像素(坐标为(x,y))。

​ 后面我们会涉及到坐标原点的平移、网格的旋转以及缩放等。

3.2 绘制矩形

​ <canvas> 只支持一种原生的 图形绘制:矩形。所有其他图形都至少需要生成一种路径(path)。不过,我们拥有众多路径生成的方法让复杂图形的绘制成为了可能。

canvast 提供了三种方法绘制矩形:

  1. fillRect(x, y, width, height) 绘制一个填充的矩形
  2. strockRect(x, y, width, height) 绘制一个矩形的边框
  3. clearRect(x, y, widh, height) 清除指定的矩形区域,然后这块区域会变的完全透明。

说明:

​ 这3个方法具有相同的参数。

​ x, y:指的是矩形的左上角的坐标。(相对于canvas的坐标原点)

​ width, height:指的是绘制的矩形的宽和高。

1 function draw(){
2     var canvas = document.getElementById('tutorial');
3     if(!canvas.getContext) return;
4     var ctx = canvas.getContext("2d");
5     ctx.fillRect(10, 10, 100, 50);  //绘制矩形,填充的默认颜色为黑色
6     ctx.strokeRect(10, 70, 100, 50);  //绘制矩形边框
7 
8 }
9 draw();
ctx.clearRect(15, 15, 50, 25);

四、绘制路径(path)

​ 图形的基本元素是路径。

​ 路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。

​ 一个路径,甚至一个子路径,都是闭合的。

使用路径绘制图形需要一些额外的步骤:

  1. 创建路径起始点
  2. 调用绘制方法去绘制出路径
  3. 把路径封闭
  4. 一旦路径生成,通过描边或填充路径区域来渲染图形。

下面是需要用到的方法:

  1. beginPath() 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
  2. moveTo(x, y) 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
  3. closePath() 闭合路径之后,图形绘制命令又重新指向到上下文中
  4. stroke() 通过线条来绘制图形轮廓
  5. fill() 通过填充路径的内容区域生成实心的图形

4.1 绘制线段

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath(); //新建一条path
 6     ctx.moveTo(50, 50); //把画笔移动到指定的坐标
 7     ctx.lineTo(200, 50);  //绘制一条从当前位置到指定坐标(200, 50)的直线.
 8     //闭合路径。会拉一条从当前点到path起始点的直线。如果当前点与起始点重合,则什么都不做
 9     ctx.closePath();
10     ctx.stroke(); //绘制路径。
11 }
12 draw();

4.2 绘制三角形边框

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath();
 6     ctx.moveTo(50, 50);
 7     ctx.lineTo(200, 50);
 8     ctx.lineTo(200, 200);
 9     ctx.closePath(); //虽然我们只绘制了两条线段,但是closePath会closePath,仍然是一个3角形
10     ctx.stroke(); //描边。stroke不会自动closePath()
11 }
12 draw();

4.3 填充三角形

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath();
 6     ctx.moveTo(50, 50);
 7     ctx.lineTo(200, 50);
 8     ctx.lineTo(200, 200);
 9 
10     ctx.fill(); //填充闭合区域。如果path没有闭合,则fill()会自动闭合路径。
11 }
12 draw();

4.4 绘制圆弧

有两个方法可以绘制圆弧:

  1. arc(x, y, r, startAngle, endAngle, anticlockwise): 以(x, y)为圆心,以r为半径,从 startAngle弧度开始到endAngle弧度结束。anticlosewise是布尔值,true表示逆时针,false表示顺时针。(默认是顺时针) 注意:
    1. 这里的度数都是弧度。
    2. 0弧度是指的x轴正方形

    radians=(Math.PI/180)*degrees //角度转换成弧度

    • 1
  2. arcTo(x1, y1, x2, y2, radius): 根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点。

圆弧案例1:

1 function draw(){
2     var canvas = document.getElementById('tutorial');
3     if (!canvas.getContext) return;
4     var ctx = canvas.getContext("2d");
5     ctx.beginPath();
6     ctx.arc(50, 50, 40, 0, Math.PI / 2, false);
7     ctx.stroke();
8 }
9 draw();

圆弧案例2:

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath();
 6     ctx.arc(50, 50, 40, 0, Math.PI / 2, false);
 7     ctx.stroke();
 8 
 9     ctx.beginPath();
10     ctx.arc(150, 50, 40, 0, -Math.PI / 2, true);
11     ctx.closePath();
12     ctx.stroke();
13 
14     ctx.beginPath();
15     ctx.arc(50, 150, 40, -Math.PI / 2, Math.PI / 2, false);
16     ctx.fill();
17 
18     ctx.beginPath();
19     ctx.arc(150, 150, 40, 0, Math.PI, false);
20     ctx.fill();
21 
22 }
23 draw();

圆弧案例3:

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath();
 6     ctx.moveTo(50, 50);
 7     //参数1、2:控制点1坐标   参数3、4:控制点2坐标  参数4:圆弧半径
 8     ctx.arcTo(200, 50, 200, 200, 100);
 9     ctx.lineTo(200, 200)
10     ctx.stroke();
11 
12     ctx.beginPath();
13     ctx.rect(50, 50, 10, 10);
14     ctx.rect(200, 50, 10, 10)
15     ctx.rect(200, 200, 10, 10)
16     ctx.fill()
17 }
18 draw();

arcTo方法的说明:

​ 这个方法可以这样理解。绘制的弧形是由两条切线所决定。

​ 第 1 条切线:起始点和控制点1决定的直线。

​ 第 2 条切线:控制点1 和控制点2决定的直线。

​ 其实绘制的圆弧就是与这两条直线相切的圆弧。

4.5 绘制贝塞尔曲线

4.5.1 什么是贝塞尔曲线

​ 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。

​ 一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。

​ 贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具如PhotoShop等。在Flash4中还没有完整的曲线工具,而在Flash5里面已经提供出贝塞尔曲线工具。

​ 贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau演算法开发,以稳定数值的方法求出贝兹曲线。

一次贝塞尔曲线(线性贝塞尔曲线)

​ 一次贝塞尔曲线其实是一条直线。

二次贝塞尔曲线

三次贝塞尔曲线

4.5.2 绘制贝塞尔曲线

绘制二次贝塞尔曲线

quadraticCurveTo(cp1x, cp1y, x, y):

说明:

​ 参数1和2:控制点坐标

​ 参数3和4:结束点坐标

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath();
 6     ctx.moveTo(10, 200); //起始点
 7     var cp1x = 40, cp1y = 100;  //控制点
 8     var x = 200, y = 200; // 结束点
 9     //绘制二次贝塞尔曲线
10     ctx.quadraticCurveTo(cp1x, cp1y, x, y);
11     ctx.stroke();
12 
13     ctx.beginPath();
14     ctx.rect(10, 200, 10, 10);
15     ctx.rect(cp1x, cp1y, 10, 10);
16     ctx.rect(x, y, 10, 10);
17     ctx.fill();
18 
19 }
20 draw();

绘制三次贝塞尔曲线

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

说明:

​ 参数1和2:控制点1的坐标

​ 参数3和4:控制点2的坐标

​ 参数5和6:结束点的坐标

 1 function draw(){
 2     var canvas = document.getElementById('tutorial');
 3     if (!canvas.getContext) return;
 4     var ctx = canvas.getContext("2d");
 5     ctx.beginPath();
 6     ctx.moveTo(40, 200); //起始点
 7     var cp1x = 20, cp1y = 100;  //控制点1
 8     var cp2x = 100, cp2y = 120;  //控制点2
 9     var x = 200, y = 200; // 结束点
10     //绘制二次贝塞尔曲线
11     ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
12     ctx.stroke();
13 
14     ctx.beginPath();
15     ctx.rect(40, 200, 10, 10);
16     ctx.rect(cp1x, cp1y, 10, 10);
17     ctx.rect(cp2x, cp2y, 10, 10);
18     ctx.rect(x, y, 10, 10);
19     ctx.fill();
20 
21 }
22 draw();

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端说吧

CSS3的transition动画功能

3326
来自专栏阮一峰的网络日志

关于颜色理论

我的意思是,我不知道应该选择哪些颜色放在一起,完全凭感觉。于是昨天,我在网上找了一些资料,希望找到理论指导。

2332
来自专栏极客猴

Python 绘图,我只用 Matplotlib(二)

上篇文章,我们了解到 Matplotlib 是一个风格类似 Matlab 的基于 Python 的绘图库。它提供了一整套和matlab相似的命令API,十分适合...

1491
来自专栏知识分享

3-关于"小五物联"的功能介绍(添加波形图,Achartengine)

2523
来自专栏程序员的诗和远方

Canvas画图基础

画矩形 Canvas画矩形还是比较方便的,可以用fillrect,clearrect,strokerect,rect几种方法,各自间有点区别,先上代码: // ...

3395
来自专栏IMWeb前端团队

移动端重构实战系列7——环形UI

本文作者:IMWeb 结一 原文出处:IMWeb社区 未经同意,禁止转载 ”本系列教程为实战教程,是本人移动端重构经验及思想的一次总结,也是对sand...

2376
来自专栏Android先生

Android自定义View——从零开始实现书籍翻页效果

前言:在上篇Android自定义View——从零开始实现书籍翻页效果(二)博客中,我们 补全了翻页效果以及增加了 取消翻页的动画,这期要教大家如何 向View填...

5652
来自专栏Modeng的专栏

canvas学习总结三:绘制路径-线段

版权声明:本文为原创文章发布于公众号:Modeng , 你可以随意转载但请务必注明出处!!! https://blog.csdn.net/qq_32135...

811
来自专栏jianhuicode

深入浅出之移动端屏幕适配(1)

说到移动端:可以根据开发技术分,也可以根据操作系统来分,今天重点不是这个,是讲下使用CSS与Android如何进行屏幕适配。 1.先来了解几个概念:CSS中的p...

23510
来自专栏cnblogs

Css3新特性应用之过渡与动画

一、缓动效果 学习和利用贝塞尔曲线,默认支持ease,ease-in,ease-out,ease-in-out和linear等 还提供一个cubic-beize...

3217

扫码关注云+社区

领取腾讯云代金券