前两章我们掌握了线段、矩形和多边形的绘制方法,今天我们主要是学习如何绘制圆弧和贝塞尔曲线。

圆弧的绘制

圆弧可以理解为一个圆上的某部分线段,在canvas中,绘制一条圆弧的语法如下:

ctx.arc( 圆心x坐标, 圆心y坐标, 圆的半径r , 开始角度, 结束角度 );

其中的 “开始角度” 和 “结束角度” 是相对360度的顺时针的极坐标而言的,可配合下图理解:

我们来一个例子,绘制一个圆心坐标为(80,80),半径为40,开始角度为30度,结束角度为90度,那么可以这样绘制:

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas> <script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.arc( 80, 80, 40, 1/6*Math.PI, 1/2*Math.PI);
ctx.stroke(); //描边
</script>

其中开始角和结束角我们分别设定为“1/6*Math.PI”和“1/2*Math.PI”,是因为canvas里的角度是以PI(π)为单位的,在js中写作Math.PI,你可以把一个PI理解为180度,那么30度便是1/6个PI。上述代码效果如下:

开始角和结束角也可以是负值,则角度从0度开始以逆时针方式获取:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.arc( 80, 80, 40, -1/6*Math.PI, -1/2*Math.PI);
ctx.stroke(); //描边

我们可以很轻松地来绘制一个完整的圆,将起始角设为0度,结束角设为360度(2*Math.PI)即可:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.arc( 80, 80, 40, 0, 2*Math.PI); ctx.lineWidth = 3; //描边宽度为3px
ctx.strokeStyle = "yellow";
ctx.stroke(); //描边
ctx.fillStyle = "#4DA6FF";
ctx.fill(); //填充颜色

注意给圆填充颜色我们使用的是 .fill() 方法,和多边形的填充方式一样。

接着说说 arc() 的好兄弟 arcTo() 方法,它可以在两条线段之间连接起一条弧线,其语法如下

ctx.arcTo( 起点切线末端x坐标, 起点切线末端y坐标, 终点x坐标, 终点y坐标, 圆的半径r );

可以配合下图理解:

我们先不管什么“连接两条线段”的事情,单纯看下arcTo()绘制了怎样的一条圆弧:

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas> <script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.moveTo(20,20); // 创建开始点
ctx.arcTo(60,20,60,60,40); // 创建圆弧路径
ctx.stroke();
</script>

效果如下:

那么我们利用arcTo()方法来连接两条直线吧:

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas> <script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.moveTo(20,20);
ctx.lineTo(60,20);
ctx.arcTo(100,20,100,60,40); // 创建圆弧路径
ctx.lineTo(100,100);
ctx.stroke();
</script>

效果如下:

需要知道的是 arc() 不会影响画笔的位置,而 arcTo() 会把画笔移到圆弧线的终点位置。

曲线的绘制

无论是arc()抑或arcTo(),均是绘制了一个正圆上的部分圆弧线段,下面讲讲更灵活的曲线的绘制。

首先介绍的是canvas中贝塞尔曲线的绘制。使用过AI等专业矢量制图软件的朋友相信能很好地理解这一部分。我们先看下在制图软件中用钢笔工具绘制一条贝塞尔曲线的过程:

可以看到每两点可以连成一条贝塞尔路径,且每一个点都有一条方位控制线来控制曲线的弯曲程度和走向,在canvas中也是以类似形式控制贝塞尔曲线的形状。

我们先来看看bezierCurveTo()的实现方式,它称作“三次方贝塞尔曲线”,其语法为:

ctx.bezierCurveTo( CSx, CSy, CEx, CEy, Ex, Ey );

其中CSx、CSy表示贝塞尔曲线起点方向控制线末端的x坐标和y坐标。CEx、CEy表示贝塞尔曲线终点方向控制线末端的x坐标和y坐标。Ex、Ey表示贝塞尔曲线终点坐标。

参考图如下,图中的贝塞尔曲线起点坐标为(20,20),终点坐标为(200,20),起点的方向控制线末端坐标为(20,100),终点的方向控制线末端坐标为(200,100):

有的朋友可能会问为何bezierCurveTo()方法没有起始点的参数,答案是起始点默认为bezierCurveTo()方法执行之前画笔所在的位置,我们可以通过ctx.moveTo(x,y)来确定起始点的位置。

如上图所示的贝塞尔曲线我们可以这样绘制:

<canvas id="myCanvas" width="300" height="150" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas> <script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.moveTo(20,20); //确定起始点
ctx.bezierCurveTo( 20, 100, 200, 100, 200, 20 );
ctx.stroke(); //描边
</script>

我们可以绘制两条或者多条连在一起的贝塞尔曲线,从而塑造我们想要的曲线:

<canvas id="myCanvas" width="400" height="250" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas> <script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.moveTo(20,120); //确定起始点
ctx.bezierCurveTo( 20, 200, 200, 200, 200, 120 ); //绘制第一条贝塞尔曲线
ctx.bezierCurveTo( 200, 20, 380, 20, 380, 120 ); //绘制第二条贝塞尔曲线,该曲线起点为上一条曲线终点(200,120)
ctx.stroke(); //描边
</script>

效果如下:

使用过矢量制图软件的朋友可能有个地方会困惑,那就是我们很多时候开始绘制一条曲线时(起点不做拉伸),该曲线的起点是没有任何方向控制线的,如下图:

如果我们要绘制一条起点不做方向控制的曲线,那么bezierCurveTo()方法就不再适用了。

针对这种情况,可以通过 quadraticCurveTo() 方法来解决,它称作“二次方贝塞尔曲线”,语法为

ctx.quadraticCurveTo( CEx, CEy, Ex, Ey );

其中CEx、CEy表示曲线终点方向控制线末端的x坐标和y坐标。Ex、Ey表示曲线终点坐标。至于曲线起点则跟bezierCurveTo()一样,为该方法执行前画笔所在的位置。

我们试着来绘制一条这样的曲线,它是我在AI中用钢笔工具绘制出来的:

它的矢量轮廓是这样的:

由于起点是没有方向控制线的,我们很容易知道得先绘制一条quadraticCurve,然后再紧接着绘制一条bezierCurve来完成这条曲线。

我们先确定下各点的坐标:

然后轻松写出代码:

<canvas id="myCanvas" width="490" height="270" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas> <script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.moveTo(52,37); //确定起始点
ctx.quadraticCurveTo( 45, 175, 172, 157 ); //绘制第一条曲线
ctx.bezierCurveTo( 298, 140, 337, 201, 312, 236 ); //绘制第二条曲线
ctx.stroke(); //描边
</script>

效果如下,杠杠的:

本章暂时写到这里,建议有兴趣的朋友多实践,其中贝塞尔曲线部分的知识点可以通过AI等矢量设计软件来加深理解。共勉~

HTML5- Canvas入门(三)的更多相关文章

  1. HTML5 canvas入门

    HTML5 Canvas入门 <canvas> 标签定义图形,比如图表和其他图像,您必须使用脚本来绘制图形.在画布上(Canvas)画一个红色矩形,渐变矩形,彩色矩形,和一些彩色的文字. ...

  2. html5 canvas 笔记三(绘制文本和图片)

    绘制文本 fillText(text, x, y [, maxWidth])   在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的. strokeText(text, x, y [, ma ...

  3. html5 Canvas绘制图形入门详解

    html5,这个应该就不需要多作介绍了,只要是开发人员应该都不会陌生.html5是「新兴」的网页技术标准,目前,除IE8及其以下版本的IE浏览器之外,几乎所有主流浏览器(FireFox.Chrome. ...

  4. HTML5 canvas绘制线条曲线

    HTML5 canvas入门 线条例子 1.简单线条 2.三角形 3.填充三角形背景颜色 4.线条颜色以及线条大小 5.二次贝塞尔曲线 6.三次贝塞尔曲线 <!doctype html> ...

  5. HTML5 Canvas 概述

    本文中,我们将探索如何使用HTML5的Canvas API.Canvas API很酷,我们可以通过它来动态创建生成和展示图形,图表,图像以及动画.本文将使用渲染API(rendering API)的基 ...

  6. Canvas入门笔记-实现极简画笔

    今天学习了Html5 Canvas入门,已经有大神写得很详细了http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html#8 在学习过后 ...

  7. HTML5 Canvas 画图入门

    HTML5 Canvas 画图入门 HTML5 Canvas 画图入门,仅供学习參考 <!DOCTYPE html> <html> <head> <meta ...

  8. HTML5 canvas 在线画笔绘图工具(三)

    组装画板(TDrawBuilder) 在这一小节中我们要把工具条和画板组装起来,让他们可以协同进行工作. 画板通过一个命名为TDrawBuilder来进行组装.在详细讲解TDrawBuilder对象之 ...

  9. [js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具)

    之前,我写了一个arc函数的用法:[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形). arcTo: cxt.arcTo( cx, cy, x2, y2, ...

  10. 06. Web大前端时代之:HTML5+CSS3入门系列~HTML5 画布

    Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 我们先看看画布的魅力: 初始画布 canvas默认是宽3 ...

随机推荐

  1. Conditional project or library reference in Visual Studio

    Conditional project or library reference in Visual Studio In case you were wondering why you haven’t ...

  2. 【leetcode】Intersection of Two Linked Lists

    题目简述: Write a program to find the node at which the intersection of two singly linked lists begins. ...

  3. asp.net core视图组件(ViewComponent)简单使用

    一.组成: 一个视图组件包括两个部分,派生自ViewComponent的类及其返回结果.类似控制器. 定义一个视图组件,如控制器一样,必须是公开,非嵌套,非抽象的类.一般,视图组件名称为类名去掉&qu ...

  4. HDU 5742 Chess SG函数博弈

    Chess Problem Description   Alice and Bob are playing a special chess game on an n × 20 chessboard. ...

  5. DOM性能瓶颈与Javascript性能优化

    这两天比较闲,写了两篇关于JS性能缺陷与解决方案的文章(<JS特性性能缺陷及JIT的解决方案>,<Javascript垃圾回收浅析>),主要描述了untyped,GC带来的问题 ...

  6. android 从 phonegap 到 js webview 交互

    像生活类.办公协同类. 动态添加,下载等. 1.phonegap 我这里用了旧的版本,可能新版本变化大了. 创建asset资源文件夹,然后新建index.html copy 相应的js 文件进来. 创 ...

  7. django _meta方法

    models.Book._meta.'concrete_model': <class 'books.models.Book'> models.Book._meta.'related_fke ...

  8. Torch Problems: require some packages doesn't work

    I've recently got a problem. require 'cutorch' doesn't work. But it was ok yesterday, although I hav ...

  9. Dertouzos (5750)

    Dertouzos 题意: 就是给一个n和一个d,问有多少个小于n的数的最大因子是d. 分析: 如果一个数是质数,又和d互质,它们的乘积在范围内的话显然是满足条件的, 如果这个质数和d不互质,那么如果 ...

  10. flex弹性盒模型布局

    容器属性:1.flex-direction:项目的排列方向(1)row 主轴方向排列(2)row-reverse 主轴反方向排列(3)column 纵向排列(4)column-reverse 纵向反方 ...