HTML5 Canvas绘图系列之一:圆弧等基础图形的实现

之前的一个微信项目已经要结项了,最近整理一下项目中使用较多的canvas画图方面的知识吧,打算写个3,4篇的样子。本篇主要介绍基础操作和弧线画法。

之后再写一下趋势图,直方图,文本图像处理的。

言归正传,canvas元素本身是一个容器元素,提供一块画布,用脚本来实现想要画什么。为了演示使用,我们新增一个空的aspx页。

首先,我们新增一个canvas元素:

    <canvas id="myConvas" style="display:block; margin: 0 auto;">
    </canvas>

style="display:block; margin: 0 auto;"作用在于使画布作为一个块元素居中。

canvas元素默认的尺寸是300(宽)*150(高),可以通过CSS来改变尺寸,例如style=" width:400px; height:300px;"

*: 改变尺寸不同浏览器有可能会导致图像拉伸,下面会有例子说明。

然后我们获取画布对象:

    var convas = document.getElementById("myConvas");//获取画布对象
    var ctx = convas.getContext("2d");//对2D平面函数库的声明,以后可以支持绘制3D图形

常用的画布元素支持的函数,下面列举一些:

函数       描述
 beginPath()  开始新路径
 moveTo()  设置路径的起始位置
 LineTo()  定义从当前位置开始的直线
 arc()        定义弧  
 arcTo()  定义从当前位置开始的弧线
 closePath()  结束路径
 stroke()  勾画路径

canvas内置的绘图形状之前只有矩形:

    ctx.fillStyle = "red"; //fillStyle属性用来设置矩形的填充颜色。不上色则默认黑色
    ctx.fillRect(50, 50, 200, 100); //方法用来绘制实心矩形,4个参数分别代表画布起始点坐标X,Y,矩形宽度,矩形高度    //ctx.strokeRect(50, 50, 200, 100); //用来绘制空心矩形,参数同上    //ctx.clearRect(50, 50, 80, 50);//用来清除某个矩形区域的内容,参数同上

3个方法效果图分别如下:

而实际应用中,我们由于审美等的要求,可能会需要圆角矩形。画圆角则涉及到画圆和圆弧的方法:

arc(x,y,radius.startAngle,endAngle,anticlockwise);六个参数中:x和y参数是圆心坐标,radius是半径,

startAngle和endAngle则是圆弧的起始角度和终止角度(以弧度表示范围为0-2π),圆心正右方点为0弧度,支持负的弧度。

anticlockwise表示做图时应该逆时针画(true)还是顺时针画(false),默认顺时针。

假如我们要花一个左上端点为(x,y)宽w,高h的圆角矩形,首先如果是非圆角矩形,那么四个顶点坐标应该为({x,y},{x+w,y},{x,y+h},{z+w,y+h})

改为圆角之后,应该是由4条线段和4段(π/2)的弧组成,我们假定画弧时候半径为R(R<w/2)&&(R<h/2)那么我们便可计算出:

左上角的2个端点{x,y+R},{x+R,y},弧线弧度为3/2π至2π ,弧线圆心坐标{x+R,y+R}

右上角的2个端点{x+w-R,y},{x+w,y+R},弧线弧度为0至1/2π,弧线圆心坐标{x+w-R,y+R}

右下角的2个端点{x+w,y+h-R},{x+w-R,y+h},弧线弧度为1/2π至π,弧线圆心坐标{x+w-R,y+h-R}

左下角的2个端点{x+r,y+h},{x,y+h-R},弧线弧度为π至3/2π,弧线圆心坐标{x+R,y+h-R}

计算完毕,开始画,代码及注释如下:

    var convas = document.getElementById("myConvas");
    var ctx = convas.getContext("2d");

    rectangle(ctx, 50, 50, 200, 80, 10);

    //非圆角是矩形左上角端点坐标(x,y,宽w,高h,圆角半径r)
    function rectangle(ctx, x, y, w, h, R) {
        //ctx.moveTo(x, y + R);//开始点,画圆弧时可以不设置起点,因为通过方法控制
        ctx.arc(x + R, y + R, R, Math.PI, Math.PI * 3 / 2);//画左上角圆弧
        ctx.arc(x + w - R, y + R, R, Math.PI * 3 / 2, Math.PI * 2); //画右上角圆弧,*当开始新画且未移动画笔时,自动连接上次画的结束点和本次起点为直线
        ctx.arc(x + w - R, y + h - R, R, 0, Math.PI / 2); //画右下角圆弧,*同上
        ctx.arc(x + R, y + h - R, R, Math.PI / 2, Math.PI); //画左下角圆弧,*同上
        ctx.lineTo(x, y + R);//画左下角至左上角直线闭合矩形
        ctx.strokeStyle = "red"; //对线条上色,不设置则默认黑色,该方法需放在stroke()方法之前
        ctx.lineWidth = 3; //设置线条宽度,不设置默认1,该方法需放在stroke()方法之前
        ctx.stroke(); //勾画路径,此时才会显示线条
    }

效果图如下:

事实上,画弧线我们也可以使用arcTo()方法来实现,这个方法对比上面那种通过计算圆心-画弧线,明显简单很多,所以圆角矩形一般使用arcTo来画

arcTo(x1,y1,x2,y2,radius),5个参数分别代表第一个点的坐标(x1,y1),第二个点的坐标(x2,y2),半径radius。

这个方法我测试了一段时间之后才明白它的意思,涉及到一个起始坐标,

1,从起始点坐标到第一个点,一条直线

2,从第一个点到第二个点,一条直线

3,2条直线必然相交(夹角显然不能为0,不然说不下去了-。-)

4,画一段圆弧,半径为randius的圆弧,与两条直线都相切!(或者延长线*j就是线段太短无法相切,所以我们去找延长线)

对照图片来说,

我们首先画了3个矩形(宽80,高100),然后分别让矩形左上角作为起始点,右上角作为第一个点,右侧直线上任选一点作为第二个点(2点确定直线。。。这个点很随意选)

半径分别为50,20,100.

前两附图都是先走直线然后弧线,第三附图是先走反向直线(及先画了反向延长线),再画圆弧来保证相切。

示例代码如下:

    //画3个矩形
    ctx.strokeRect(10, 50, 80, 100)
    ctx.strokeRect(110, 50, 80, 100)
    ctx.strokeRect(210, 50, 80, 100)
    //画第一条弧线
    ctx.moveTo(10, 50);
    ctx.arcTo(90, 50, 90, 80, 50);
    //画第二条弧线
    ctx.moveTo(110, 50);
    ctx.arcTo(190, 50, 190, 80, 20);
    //画第三条弧线
    ctx.moveTo(210, 50);
    ctx.arcTo(290, 50, 290, 80, 100);
    ctx.strokeStyle = "red"; //对线条上色,不设置则默认黑色,该方法需放在stroke()方法之前
    ctx.stroke();

看到这里就应该明白使用arcTo()画圆角比arc()简单很多了吧~先难后易的讲法楼主自己也是感觉醉了,

这篇写了这么多基础介绍,下面写一个实际的小应用示例来收尾吧!

我们来实现在网页插入头像图片,环绕头像图片画一定宽度弧线作为能量槽,  随时间变化弧线一小段一小段变色。

实现思路呢:

1,定义好一个图片位置,定义画布位置,环绕图片画一定宽度弧线,上底色

2,定义延时自动执行的函数,每隔一定时间新画一段新的圆弧,上色,覆盖底色

3,覆盖完毕,延时函数不再调用自身。

实现意义呢:

1,我们画图往往通过覆盖来实现页面,为下一篇画直方图等做铺垫

2,这个画图可以通过ajax等获取后台数据源绑定,并定时刷新图的趋势体现数据。

下面先贴上代码注释和效果图片,把下面代码拷贝到VS一个aspx页面,然后右键浏览器查看也能看到效果。

图片之后,文章末尾会总结一下易出错点。

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Canvas.aspx.cs" Inherits="Canvas" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <img src="http://p2.wmpic.me/article/2014/09/29/1411980934_pnKerJNu.png" style="display: block; margin: 0 auto;" />
    <canvas id="myConvas" style="display: block; margin: 0 auto; position: absolute;
        top: 5px; left: 500px; width: 500px; height: 250px;">
    </canvas>
</body>
<script type="text/javascript">
    var convas = document.getElementById("myConvas");
    var ctx = convas.getContext("2d");
    //ctx.fillStyle = "red"; //fillStyle属性用来设置矩形的填充颜色。
    //ctx.fillRect(50, 50, 200, 100); //方法用来绘制矩形,4个参数分别代表画布起始点坐标X,Y,矩形宽度,矩形高度
    //ctx.strokeRect(50, 50, 200, 100); //用来绘制空心矩形,参数同上。
    //ctx.clearRect(50, 50, 80, 50);//用来清除某个矩形区域的内容,参数同上。
    //rectangle(ctx, 50, 50, 200, 80, 10);
    //画3个矩形
    //    ctx.strokeRect(10, 50, 80, 100)
    //    ctx.strokeRect(110, 50, 80, 100)
    //    ctx.strokeRect(210, 50, 80, 100)
    //    //画第一条弧线
    //    ctx.moveTo(10, 50);
    //    ctx.arcTo(90, 50, 90, 80, 50);
    //    //画第二条弧线
    //    ctx.moveTo(110, 50);
    //    ctx.arcTo(190, 50, 190, 80, 20);
    //    //画第三条弧线
    //    ctx.moveTo(210, 50);
    //    ctx.arcTo(290, 50, 290, 80, 100);
    //    ctx.strokeStyle = "red"; //对线条上色,不设置则默认黑色,该方法需放在stroke()方法之前
    //    ctx.stroke();

    //先画一层红色底色
    ctx.beginPath();//路径开始
    ctx.arc(132, 61, 65, Math.PI * 1.7, Math.PI * 1.3, false);//画圆弧,从图片正上方偏右画到正上方偏左
    ctx.lineWidth = 3;//设置线宽
    ctx.strokeStyle = "red";//上红色
    ctx.stroke();//画出路径
    ctx.closePath();//结束路径
    //点击图片上蓝色
    var count = 1;
    //延时函数执行,每次覆盖0.1* PI红色,变一段为黄色,直至覆盖完毕,我们将弧线分成16份
    alarmWaiting(count);
    function alarmWaiting(count) {
        count++;
        //每次执行多覆盖0.1,共执行16次
        if ((count > 3) && (count < 20)) {

            //计算出本次覆盖结束的弧度
            var end = (1.7 + (count - 3) * 0.1) >= 2.0 ? (1.7 + (count - 3) * 0.1) - 2.0 : (1.7 + (count - 3) * 0.1);
            //移动至图片正上方偏右位置起始点坐标
            ctx.moveTo(132 + 65 * Math.cos(Math.PI * 1.7), 61 + 65 * Math.sin(Math.PI * 1.7));
            ctx.beginPath();
            //画黄色弧线覆盖红色
            ctx.arc(132, 61, 65, Math.PI * 1.7, Math.PI * end, false);
            ctx.lineWidth = 3;
            ctx.strokeStyle = "yellow";
            ctx.stroke();
            ctx.closePath();//结束
        }
        if (count < 20) {
            //小于20,(即圆弧分为16份),每次隔2000ms(2秒后)执行调用function () { alarmWaiting(count) }匿名方法。count为19时全部覆盖为黄色
            setTimeout(function () { alarmWaiting(count) }, 2000);
        }
    }

    //非圆角是矩形左上角端点坐标(x,y,宽w,高h,圆角半径r)
    function rectangle(ctx, x, y, w, h, R) {
        //ctx.moveTo(x, y + R);//开始点,画圆弧时可以不设置起点,因为通过方法控制
        ctx.arc(x + R, y + R, R, Math.PI, Math.PI * 3 / 2); //画左上角圆弧
        ctx.arc(x + w - R, y + R, R, Math.PI * 3 / 2, Math.PI * 2); //画右上角圆弧,*当开始新画且未移动画笔时,自动连接上次画的结束点和本次起点为直线
        ctx.arc(x + w - R, y + h - R, R, 0, Math.PI / 2); //画右下角圆弧,*同上
        ctx.arc(x + R, y + h - R, R, Math.PI / 2, Math.PI); //画左下角圆弧,*同上
        ctx.lineTo(x, y + R); //画左下角至左上角直线闭合矩形
        ctx.strokeStyle = "red"; //对线条上色,不设置则默认黑色,该方法需放在stroke()方法之前
        ctx.lineWidth = 3; //设置线条宽度,不设置默认1,该方法需放在stroke()方法之前
        ctx.stroke(); //勾画路径,此时才会显示线条
    }
</script>
</html>

效果图片如下:

在这个小页面的实现过程中,有以下几点需要注意下:

1,  position: absolute;top: 5px; left: 500px; 这个定位,当上级元素没有position时候,使用absolute按浏览器左上角为(0.0)绝对定位,

如果不加这个的话,你会发现图片和画布无法重叠。(2者并列关系,其实画布也可以导入图片并编辑)

2, 关于匿名方法,setTimeout(function () { alarmWaiting(count) }, 2000);这段当调用函数没有实参时候可以写成setTimeout( alarmWaiting() , 2000);

但是有实参时候 写成setTimeout( alarmWaiting(count) , 2000);是错误的,你会发现没有延时2秒执行,而是执行所有遍数没有延时,这是或许是因为

alarmWaiting(count)无 法被转化识别为付出function (),导致系统立即执行alarmWaiting希望得到返回一个function ()但是!失败,达不到相应的效果

3,圆周上的点根据弧度计算坐标,这个就不细说了,注意到是0度是正右方,而我们实际绘图往往以正上方为起点,即1.5*PI或者是-0.5*PI

4,如上条所说,支持负的弧度运算等价于加2*PI的倍数换算为的正弧度

5,beginPath()和closePath();开始和结束路径,如果你想做覆盖图形,上一个图形一定要先结束!!!然后再开始下一个覆盖,“亲身踩过的雷,默泪!”

6,关于画布上的点点击事件,可以通过计算来触发,(需要注意到是换算像素点要考虑浏览器和下拉条),之前有个方法回头我再补上吧,

好吧,凌晨1点半了,睡了that‘s  all~

时间: 2024-10-01 07:31:16

HTML5 Canvas绘图系列之一:圆弧等基础图形的实现的相关文章

html5 canvas绘图-贝塞尔曲线

贝塞尔曲线(ezier curve)最迟是由法国物理学家与数学家paul de Casteljau发明的.它的广泛运用则要归功于法国工程师皮埃尔 贝塞尔 贝塞尔曲线期初被用在汽车车身的设计上.现在则多用于计算机图形系统中.例如Adobe Illustrator/Apple的Cocoa框架以及在Html5的canvas. 贝塞尔曲线分为两种:平方(quadratic)贝塞尔曲线及立方(cubic)贝塞尔曲线.平方贝塞尔曲线是一种二次曲线(second degree curve),意思就是说,它们是

HTML5 Canvas 绘图入门

HTML5 Canvas 绘图入门 HTML5 Canvas 绘图入门,仅供学习参考 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>HTML5 移动Web开发指南</title> <style type="text/css"> h1, h5 { text-align: center; } canvas {

HTML5 canvas绘图基本使用方法

<canvas></canvas>是HTML5中新增的标签,用于绘制图形,实际上,这个标签和其他的标签一样,其特殊之处在于该标签可以获取一个CanvasRenderingContext2D对象,我们可以通过JavaScript脚本来控制该对象进行绘图. <canvas></canvas>只是一个绘制图形的容器,除了id.class.style等属性外,还有height和width属性.在<canvas>>元素上绘图主要有三步: 获取<

html5 canvas绘图-刻度仪表盘的绘制

---恢复内容开始--- 圆弧,尤其是圆,通常被用做描绘一些实物.下图所示的应用程序用5个圆形实现了一个仪表盘.仪表盘的刻度代表了圆周上的角度值.用户可以通过它来交互式地旋转多边形物体. 该应用程序使用了本章到目前为止所讲的很多技术.为了绘制这个仪表盘,该应用程序画了许多圆形与线段,使用了各种颜色及透明度,对圆形路径进行了描边与填充.同时为了使盘面上的刻度看起来有深度感,它还运用了阴影效果.该程序还运用了剪纸效果.使得仪表盘外围的那一圈看起来有半透明的效果. 仪表盘的绘制 html代码: 1 <

HTML5 canvas绘图

HTML5 canvas画图 示例 ------- <!DOCTYPE html> <head> <meta charset="UTF-8"> <script src="jquery-3.1.1.min.js"></script> <link rel="stylesheet" type="text/css" href="style.css"

android Canvas 绘图系列(一)

首先解释一下:Canvas.Paint .Rect. Canvas绘图有三个要点(你完全可以开一下脑洞): 1.Canvas画布,就像是我们画画用的纸.图形绘制在Canvas画布之上. 2.Paint画笔,就像现实中的画笔一样,可以设置颜色,字体,透明度等. 3.Rect绘画路径,用于绘制不同形状如:矩形.椭圆形等. 这里主要讲述的是View中的onDraw 中的canvas参数,至于画板之类的暂且不提. 在自定义控件中常重写父类onDraw改变view的属性. view源码中的onDraw方法

HTML5 Canvas游戏开发(一)基础知识

一.绘制基本图形 在每次用canvas画布时,都有几步是“套路” 1.在HTML中创建Canvas画布: <canvas id="mycanvas" width="960px" height="580px"> 浏览器不支持canvas <!-- 如果不支持会显示这段文字 --> </canvas> 2.获取画布标签,并得到一个2D对象: var c = document.getElementById('myca

HTML5 Canvas绘图详解 drawImage() 方法 有图有真相!

步骤 1 2 3 4 5 简介 是一个新的HTML元素,这个元素可以被Script语言(通常是JavaScript)用来绘制图形.例如可以用它来画图.合成图象.或做简单的(和不那么简单的)动画. 工具/原料 html script 步骤/方法 最常见的在canvas上画图的方法是使用Image对象.所支持的来源图片格式依赖于浏览器的支持,然而,一些典型的图片格式(png,jpg,gif等)基本上都没有问题. 在下面的所有例子中,图片源将会使用这张256×256尺寸的图片. 绘制图片:在最基本的画

html5 canvas绘图—三次方贝塞尔曲线

我们知道二次方贝塞尔曲线,那些曲线都是二维的,意思就是说,它们都只能向一个方向弯曲.如果需要如图这样,能够向两个方向弯曲的曲线,那么你需要的就是三次贝塞尔曲线. 该图所示应用程序使用bezierCurveTo()方法创建了一条代表三次方贝塞尔曲线的路径.该应用程序的代码列在了下面的程序清单中. 这段代码除了绘制曲线本身,还填充了表示曲线控制点与锚点的小圆圈. html代码: 1 <html> 2 <head> 3 <title>Bezier Curves</tit