一、贝塞尔曲线
1.1 什么贝塞尔曲线
贝塞尔曲线(Bézier curve),是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。
贝塞尔曲线是计算机图形学中相当重要的参数曲线,它通过一个方程来描述一条曲线,根据方程的最高阶数,又可以分为线性贝塞尔曲线、二次贝塞尔曲线三次贝塞尔曲线和更高阶的贝塞尔曲线。
1)二次贝塞尔曲线
二次贝塞尔曲线由三个点P0、P1、P2来确定,这些点也被称为控制点,如下图:
对于二次贝塞尔曲线的绘制我们可以这样理解:
- 首先在线段P0P1和P1P2上分别选取一个点Q0、Q1,使得P0Q0 / P0P1 = P1Q1 / P1P2 = t,t 的取值范围在[0,1];
- 连接Q0、Q1,在线段Q0Q1上选取一个点B,使得Q0B / Q0Q1 = P0Q0 / P0P1 = P1Q1 / P1P2 = t,此时B就是曲线上的一点;
- 将t的值从0过渡到1,不断重复上面的步骤,计算出所有的点B,连接所有符合条件的点B,就可以得到一条二次贝塞尔曲线。
2)三次贝塞尔曲线
三次贝塞尔曲线由四个点P0、P1、P2、P3来确定,这些点也被称为控制点,如下图:
三次贝塞尔曲线的绘制与二次贝塞尔曲线类似,只是他多了一个控制点,因此找点B的过程比二次贝塞尔多了几个步骤:
- 首先在线段P0P1、P1P2、P2P3上分别选取一个点Q0、Q1、Q2,使得P0Q0 / P0P1 = P1Q1 / P1P2 = P2Q2 / P2P3 = t,t 的取值范围在[0,1];
- 连接Q0、Q1,Q1、Q2,分别在线段Q0Q1、Q1Q2上选取一个点R0、R1,使得Q0R0 / Q0Q1 = Q1R1 / Q1Q2 = t;
- 连接R0、R1,在线段R0R1上选取一个点B,使得R0B / R0R1 = t,此时B就是曲线上的一点;
- 将t的值从0过渡到1,不断重复上面的步骤,计算出所有的点B,连接所有符合条件的点B,就可以得到一条三次贝塞尔曲线。
1.2 绘制贝塞尔曲线
canvas提供了绘制二次贝塞尔曲线和三次贝塞尔曲线的方法
1)二次贝塞尔曲线
quadraticCurveTo(cx, cy, x, y):从当前位置开始绘制一条二次贝塞尔曲线,到(x, y)为止,并且以(cx, cy)作为控制点。
1 var canvas = document.getElementById('my-canvas'); 2 if (canvas.getContext) { 3 var ctx = canvas.getContext('2d'); 4 ctx.beginPath(); 5 ctx.moveTo(50, 200); // 起始点 6 ctx.quadraticCurveTo(100, 50, 250, 230); // (100, 50):控制点;(250,230):结束点 7 ctx.stroke(); 8 9 ctx.beginPath(); 10 ctx.fillRect(50, 200, 5, 5); // 标记起始点的矩形 11 ctx.fillRect(100, 50, 5, 5); // 标记控制点的矩形 12 ctx.fillRect(250, 230, 5, 5); // 标记结束点的矩形 13 }
2)三次贝塞尔曲线
bezierCurveTo(cx1, cy2, cx2, cy2, x, y):从当前位置绘制一条三次贝塞尔曲线,到(x, y)为止,并且以(cx1, cy1)、(cx2, cy2)作为控制点
1 var canvas = document.getElementById('my-canvas'); 2 if (canvas.getContext) { 3 var ctx = canvas.getContext('2d'); 4 ctx.beginPath(); 5 ctx.moveTo(50, 200); // 起始点 6 ctx.bezierCurveTo(80, 50, 180, 30, 250, 230); // (80, 50)、(180, 30):控制点1;(250,230):结束点 7 ctx.stroke(); 8 9 ctx.beginPath(); 10 ctx.fillRect(50, 200, 5, 5); // 标记起始点的矩形 11 ctx.fillRect(80, 50, 5, 5); // 标记控制点1的矩形 12 ctx.fillRect(180, 30, 5, 5); // 标记控制点2的矩形 13 ctx.fillRect(250, 230, 5, 5); // 标记结束点的矩形 14 }
二、绘制文本
文本与图形总是如影随形,因此canvas也提供了两种绘制文本的方法:
strokeText(text, x, y [, maxWidth] )
fillText(text, x, y [, maxWidth] )
参数说明:
- text:表示要绘制的文本字符串
- x:x坐标
- y:y坐标
- maxWidth:绘制的最大宽度,可选参数
同时canvas也提供了三个属性用于给本文添加样式:
- font:用于设置文本样式、大小和字体,该属性值为字符串,且与CSS中font属性的语法相同,默认为:' 10px sans-serif '。
- textAlign:用于设置文本对齐方式,可选值有start、end、left、right、center,默认值为start。
- textBaseline:用于设置文本基线对齐方式,可选值有top、hanging、middle、alphabetic、ideographic、bottom,默认值为alphabetic。
1 var canvas = document.getElementById('my-canvas'); 2 if (canvas.getContext) { 3 var ctx = canvas.getContext('2d'); 4 ctx.font = '20px 宋体'; 5 ctx.textAlign = 'start'; 6 ctx.textBaseline = 'top'; 7 ctx.fillText('做自己的铠甲', 150, 50); 8 9 ctx.textAlign = 'center'; 10 ctx.textBaseline = 'middle'; 11 ctx.strokeText('如人饮水', 150, 150); 12 13 ctx.textAlign = 'end'; 14 ctx.textBaseline = 'bottom'; 15 ctx.fillText('冷暖自知', 150, 250); 16 17 ctx.beginPath(); 18 ctx.fillStyle = 'red'; 19 ctx.fillRect(150, 50, 5, 5); // 标记第一句话(x, y)坐标的矩形 20 ctx.fillRect(150, 150, 5, 5); // 标记第二句话(x, y)坐标的矩形 21 ctx.fillRect(150, 250, 5, 5); // 标记第三句话(x, y)坐标的矩形 22 }
根据代码的运行结果我们可以发现:
当把属性textAlign设置为start、textBaseline设置为top时,坐标(x, y)实际上就是文本水平起点和垂直顶点的坐标;
当把属性textAlign设置为center、textBaseline设置为middle时,坐标(x, y)实际上就是文本水平中点和垂直中点的坐标;
当把属性textAlign设置为end、textBaseline设置为bottom时,坐标(x, y)实际上就是文本水平终点和垂直终点的坐标;
因此,文本的textAlign属性值和textBaseline属性值表示的是,坐标为(x, y)这个点相对于文本在水平和垂直方向上的位置。