Canvas教程(5)——绘制矩形

使用closePath()闭合图形

首先我们用上节课的方法绘制一个矩形。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>绘制矩形</title>
</head>
<body>
<div id="canvas-warp">
    <canvas id="canvas" style="border: 1px solid #aaaaaa; display: block; margin: 50px auto;">
        你的浏览器居然不支持Canvas?!赶快换一个吧!!
    </canvas>
</div>

<script>
    window.onload = function(){
        var canvas = document.getElementById("canvas");
        canvas.width = 800;
        canvas.height = 600;
        var context = canvas.getContext("2d");

        context.beginPath();
        context.moveTo(150,50);
        context.lineTo(650,50);
        context.lineTo(650,550);
        context.lineTo(150,550);
        context.lineTo(150,50);     //绘制最后一笔使图像闭合
        context.lineWidth = 5;
        context.strokeStyle = "black";
        context.stroke();

    }
</script>
</body>
</html>
</body>
</html>

演示 5-1

运行结果:

绘制矩形

乍一看没啥问题,但是视力好的童鞋已经发现了,最后一笔闭合的时候有问题,导致左上角有一个缺口。这种情况是设置了lineWidth导致的。如果默认1笔触的话,是没有问题的。但是笔触越大,线条越宽,这种缺口就越明显。那么这种情况该怎么避免呢?

标题已经剧透了,使用clothPath()闭合图形。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>绘制矩形</title>
</head>
<body>
<div id="canvas-warp">
    <canvas id="canvas" style="border: 1px solid #aaaaaa; display: block; margin: 50px auto;">
        你的浏览器居然不支持Canvas?!赶快换一个吧!!
    </canvas>
</div>

<script>
    window.onload = function(){
        var canvas = document.getElementById("canvas");
        canvas.width = 800;
        canvas.height = 600;
        var context = canvas.getContext("2d");

        context.beginPath();
        context.moveTo(150,50);
        context.lineTo(650,50);
        context.lineTo(650,550);
        context.lineTo(150,550);
        context.lineTo(150,50);     //最后一笔可以不画
        context.closePath();        //使用closePath()闭合图形

        context.lineWidth = 5;
        context.strokeStyle = "black";
        context.stroke();

    }
</script>
</body>
</html>
</body>
</html>

演示 5-2

运行结果:

使用closePath()闭合图形

这个例子结合上节课的讲解,我们知道了绘制路径的时候需要将规划的路径使用beginPath()closePath()包裹起来。当然,最后一笔可以不画出来,直接使用closePath(),它会自动帮你闭合的。(所以如果你不想绘制闭合图形就不可以使用closePath())

给矩形上色

这里我们要介绍一个和stroke()同等重要的方法fill()。和当初描边一样,我们在填色之前,也要先用fillStyle属性选择要填充的颜色。

比如我们要给上面的矩形涂上黄色,可以这样写。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>绘制矩形</title>
</head>
<body>
<div id="canvas-warp">
    <canvas id="canvas" style="border: 1px solid #aaaaaa; display: block; margin: 50px auto;">
        你的浏览器居然不支持Canvas?!赶快换一个吧!!
    </canvas>
</div>

<script>
    window.onload = function(){
        var canvas = document.getElementById("canvas");
        canvas.width = 800;
        canvas.height = 600;
        var context = canvas.getContext("2d");

        context.beginPath();
        context.moveTo(150,50);
        context.lineTo(650,50);
        context.lineTo(650,550);
        context.lineTo(150,550);
        context.lineTo(150,50);     //最后一笔可以不画
        context.closePath();        //使用closePath()闭合图形

        context.fillStyle = "yellow";   //选择油漆桶的颜色
        context.lineWidth = 5;
        context.strokeStyle = "black";

        context.fill();                 //确定填充
        context.stroke();

    }
</script>
</body>
</html>
</body>
</html>

演示 5-3

运行结果:

给矩形上色

这里需要注意的是一个良好的编码规范。因为之前说过了Canvas是基于状态的绘制,只有调用了stroke()fill()才确定绘制。所以我们要把这两行代码放在最后,其余的状态设置的代码放在它们之前,将状态设置确定绘制的代码分隔开。增强代码的可读性。

封装绘制方法

大家一定发现了,绘制矩形其实都是这样的四笔,我们每次用这种笨方法画矩形都要画这四笔有多麻烦,如果我们要花10个矩形?100个?1000个?都这样写,代码会臃肿,复用性很低。这里,我们可以使用JavaScript封装这些方法。我们知道,一个矩形可以由它的左上角坐标和其长宽唯一确定。

JavaScript函数

这里我们介绍一下JavaScript函数。如果有基础的同学可以跳过这一大段,直接看后面的。

JavaScript 和 ActionScript 语言的函数声明调用一样,都是编程语言中最简单的。

函数的作用

函数的作用,可以写一次代码,然后反复地重用这个代码。如:我们要完成多组数和的功能。

var sum;   
sum = 3+2;
alert(sum);

sum=7+8 ;
alert(sum); 

....  //不停重复两行代码

如果要实现8组数的和,就需要16行代码,实现的越多,代码行也就越多。所以我们可以把完成特定功能的代码块放到一个函数里,直接调用这个函数,就省去重复输入大量代码的麻烦。

使用函数完成:

function add2(a,b){
    sum = a + b;
    alert(sum);
} //  只需写一次就可以

add2(3,2);
add2(7,8);
....  //只需调用函数就可以

定义函数

如何定义一个函数呢?看看下面的格式:

function  函数名( )
{
     函数体;
}

function定义函数的关键字,“函数名”你为函数取的名字,“函数体”替换为完成特定功能的代码。

函数调用

函数定义好后,是不能自动执行的,需要调用它,直接在需要的位置写函数名。一般有两种方式:

  • 第一种情况:在<script>标签内调用。
<script>
function tcon()
{
    alert("恭喜你学会函数调用了!");
}
tcon(); //调用函数,直接写函数名。
</script>
  • 第二种情况:在HTML文件中调用,如通过点击按钮后调用定义好的函数。

这种情况以后用到了再说。

有参数的函数

格式如下:

function 函数名(参数1,参数2)
{
     函数代码
}

注意:参数可以多个,根据需要增减参数个数。参数之间用(逗号,)隔开。

按照这个格式,函数实现任意两个数的和应该写成:

function add2(x,y)
{
   sum = x + y;
   document.write(sum);
}

x和y则是函数的两个参数,调用函数的时候,我们可通过这两个参数把两个实际的加数传递给函数了。

例如,add2(3,4)会求3+4的和,add2(60,20)则会求出60和20的和。

返回值函数

function add2(x,y)
{
   sum = x + y;
   return sum; //返回函数值,return后面的值叫做返回值。
}

这里的return和其他语言中的一样,但是在JS或者AS等弱类型语言中,返回值类型是不需要写到函数声明里的。


至此,我们把JavaScript函数也顺便系统的说了一下。下面回到正题~

我们也可以封装一下我们的矩形,代码如下:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>封装绘制矩形方法</title>
</head>
<body>
<div id="canvas-warp">
    <canvas id="canvas" style="border: 1px solid #aaaaaa; display: block; margin: 50px auto;">
        你的浏览器居然不支持Canvas?!赶快换一个吧!!
    </canvas>
</div>

<script>
    window.onload = function(){
        var canvas = document.getElementById("canvas");
        canvas.width = 800;
        canvas.height = 600;
        var context = canvas.getContext("2d");

        drawRect(context, 150, 50, 50, 50, "red", 5, "blue");
        drawRect(context, 250, 50, 50, 50, "green", 5, "red");
        drawRect(context, 350, 50, 50, 50, "yellow", 5, "black");
    }

    function drawRect(cxt, x, y, width, height, fillColor, borderWidth, borderColor){
        cxt.beginPath();
        cxt.moveTo(x, y);
        cxt.lineTo(x + width, y);
        cxt.lineTo(x + width, y + height);
        cxt.lineTo(x, y + height);
        cxt.lineTo(x, y);
        cxt.closePath();

        cxt.lineWidth = borderWidth;
        cxt.strokeStyle = borderColor;
        cxt.fillStyle = fillColor;

        cxt.fill();
        cxt.stroke();
    }
</script>
</body>
</html>
</body>
</html>

演示 5-4

运行结果:

封装绘制矩形方法

使用rect()方法绘制矩形

犹豫绘制矩形是常用的方法,所以在Canvas API中已经帮我们封装好了一个绘制矩形的方法——rect()。这个方法接收4个参数x, y, width, height,实际调用时也就是

context.rect(x,y,width,height);

基于此,我们帮刚才封装的方法优化一下。

function drawRect(cxt, x, y, width, height, fillColor, borderWidth, borderColor){
        cxt.beginPath();
        cxt.rect(x, y, width, height);
        //cxt.closePath();    可以不用closePath()

        cxt.lineWidth = borderWidth;
        cxt.strokeStyle = borderColor;
        cxt.fillStyle = fillColor;

        cxt.fill();
        cxt.stroke();
}

调用封装方法,绘制魔性图像

还记得我们第三节开头那个魔性的图像吗?


度娘魔性图

好,我们就拿它开刀,练练手,给咱刚封装好的方法活动活动筋骨。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>绘制魔性图形</title>
</head>
<body>
<div id="canvas-warp">
    <canvas id="canvas" style="border: 1px solid #aaaaaa; display: block; margin: 50px auto;">
        你的浏览器居然不支持Canvas?!赶快换一个吧!!
    </canvas>
</div>

<script>
    window.onload = function() {
        var canvas = document.getElementById("canvas");
        canvas.width = 800;
        canvas.height = 600;
        var context = canvas.getContext("2d");
        context.beginPath();
        context.rect(0, 0, 800, 600);
        context.fillStyle = "#AA9033";
        context.fill();
        context.beginPath();
        for(var i=0; i<=20; i++){
            drawWhiteRect(context, 200 + 10 * i, 100 + 10 * i, 400 - 20 * i, 400 - 20 * i);
            drawBlackRect(context, 205 + 10 * i, 105 + 10 * i, 390 - 20 * i, 390 - 20 * i);
        }
        context.beginPath();
        context.rect(395, 295, 5, 5);
        context.fillStyle = "black";
        context.lineWidth = 5;
        context.fill();
        context.stroke();
    }
        function drawBlackRect(cxt, x, y, width, height) {
            cxt.beginPath();
            cxt.rect(x, y, width, height);
            cxt.lineWidth = 5;
            cxt.strokeStyle = "black";
            cxt.stroke();
        }
        function drawWhiteRect(cxt, x, y, width, height) {
            cxt.beginPath();
            cxt.rect(x, y, width, height);
            cxt.lineWidth = 5;
            cxt.strokeStyle = "white";
            cxt.stroke();
        }
</script>
</body>
</html>

演示 5-5

运行结果:

魔性正方形

是不是很有魔性?是不是非常的酷?这段代码就不花篇幅解释了,大家自己课下琢磨琢磨,也可以尝试着用已经学过的知识去绘制一个酷酷的图像。这节课内容有点多,其实也只是介绍了四个属性和方法——closePath()fillStylefill()rect(),还有一个扩展的JavaScript函数讲解。

好了,多花点时间消化消化。然后我们带着我们完成的艺术品,继续前进~😋


如果您喜欢本书,请使用支付宝扫描下面的二维码捐助作者。

二维码

谢谢您的支持!也欢迎您订阅本书。

如果书中有疏漏或错误之处,敬请您指出,期待您的pull request。如果有任何疑问也可以发送issue。

本人邮箱:airing@ursb.me

本人博客:http://ursb.me

本书地址:http://airingursb.gitbooks.io/canvas

本书github:http://github.com/airingursb/canvas

Canvas--Draw on the Web
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容

  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,687评论 2 32
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,198评论 25 707
  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。它提供了低...
    ShanJiJi阅读 1,537评论 0 20
  • 选择了开始,就别轻易放弃,因为放弃的代价更高。一旦你下次再开始,就意味着你之前的努力是做无用功。 我记得这句话我几...
    读书少的丝瓜阅读 306评论 0 2
  • 您活的太累了。 就在前几天,我们一块聊天,您又在说:村里那个谁谁他看不起我!我问:您是怎么判断出他看不起您的?您用...
    Z和风细雨M阅读 254评论 5 10