canvas 订阅
《canvas》是从2005年10月3日开始放映的24集日本动画,由F&C ZEXCS制作发行,讲述了拥有超人的绘画天分的男主角的故事。 展开全文
《canvas》是从2005年10月3日开始放映的24集日本动画,由F&C ZEXCS制作发行,讲述了拥有超人的绘画天分的男主角的故事。
信息
外文名
Canvas
制作·发行
F&C ZEXCS
放映日期
2005年10月3日
日文名
虹色のスケッチ
国    家
日本
总共集数
24
canvas剧情简介
拥有超人的绘画天分的男主角,却因某事故无法再次执起画笔,只能委身于某所大学,担任美术课的顾问。受男主角指导走向绘画之路的女主角,却因目睹双亲车祸身亡的现场,而在作画中无法使用红色。青梅竹马的女伴,可是高中时代的告白,却遭到男主角的拒绝,现在她又重新闯入了男主角的生活。 偶然的再会…… 三人之间,会发生什么?爱的前路,会走向哪里?
收起全文
精华内容
参与话题
问答
  • web前端:Canvas 基础(一)

    万次阅读 多人点赞 2017-11-01 18:02:44
    web前端:Canvas 基础(一)

    0.前言

    最近忙里偷闲,来写写文章。

    ————-我是华丽的分割线————–

    终于把这篇文章写完了,关于本文,针对读者主要是之前从未接触过 Canvas的同学。当然,你要学 canvas 一定要有 JS 基础啦。

    其次就是,因为前前后后耽误了两天时间,可能在书写和描述中出现一些小的纰漏,请各位读者老爷见谅。

    最后,也希望这篇文章能够对迷茫的你产生一些帮助,感谢。

    1. canvas 简介


    1.1 canvas 是什么?

    是HTML5中重要的元素,和audio、video元素类似完全不需要任何外部插件就能够运行.

    Canvas中文翻译就是”画布”.它提供了强大的图形的处理功能(绘制,变换,像素处理…)。

    但是需要注意,canvas 元素本身并不绘制图形,它只是相当于一张空画布。

    如果开发者需要向 canvas 上绘制图形,则必须使用 JavaScript 脚本进行绘制。

    1.2 canvas 能够做什么?

    • 基础图形的绘制
    • 文字的绘制
    • 图形的变形和图片的合成
    • 图片和视频的处理
    • 动画的实现
    • 小游戏的制作

    1.3 支持的浏览器

    大多数现代浏览器都是支持Canvas的,比如 Firefox, safari, chrome, opera的最近版本以及IE9都支持.

     IE8及以下不支持HTML5,但是我们可以进行提示用户更新到最新的版本

    1.4 关于canvas 标签的基本概念

    在 HTML 页面上定义 canvas 元素与定义其他普通元素并无任何不同,它吃了可以指定 id, style ,class ,hidden 等通用属性之外,还可以设置 width 和 height 两个属性。

    为什么要特意去说这个呢?

    咱们在 章节 2.2 中详细去说明。

    除此之外,我们在网页中定义 canvas 元素之后,它只是一张空白的画布,想要在画布上绘画,一定要经过下面几步。

    1. 获取 canvas 元素对应的 DOM 对象,这必须是一个 canvas 对象
    2. 调用 canvas 对象的 getContext( ) 方法,该方法返回一个 canvasRenderingContext2D 对象,该对象可以绘制图形。
    3. 调用 canvasRenderingContext2D 对象的方法进行绘图。

    那么我们就来开始我们的canvas 实战,来看看 canvas 该如何会绘制图形。

    2.canvas 实战


    2.1 查看当前浏览器对 canvas 的支持情况

    我们在上面也说明了,我们的一些浏览器是不支持 canvas 的,这个时候我们应该怎么去做呢?

    这时候我们可以直接在 canvas 标签之间去书写内容,这么做的好处是当你的浏览器不支持 canvas 的时候,我们可以去展示标签之间的内容,具体如下。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style type="text/css">
            html,body{
                margin: 0px;
            }
            canvas{
                background: #ccc;
            }
        </style>
    </head>
    <body>
        <canvas>
            我们在设置 canvas 之前需要首先监测用户电脑是否支持 canvas
        </canvas>
    </body>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    既然已经创建完成了具体的内容,那我们现在可以看见了么?

    我们虽然没有给定 canvas 的宽度和高度,但是实际上我们的canvas 在页面中是可见的

    需要注意,canvas 默认样式的宽度和高度 是 300px * 150px.

    即使我们不去设置具体的宽度和高度,它也是可以显示的。

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>Document</title>
     <style type="text/css">
      html,body{
       margin: 0px;
      }
      canvas{
       background: #ccc;
      }
     </style>
    </head>
    <body>
     <canvas>
      我们在设置 canvas 之前需要首先监测用户电脑是否支持 canvas
     </canvas>
    </body>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.png

    那我们该如何去修改画布的默认大小呢?

    2.2 修改 Canvas 的画布

    按照我们正常的思路来说,我们会直接去使用 canvas_1.style.width = "500px"; 来去修改我们的 canvas 的宽度,但是这样真的对么?

    答案当然是否定的,canvas 相当于是一张图片,如果我们设置 <canvas width="500" height="500">.

    这样写相当于图片的实际大小是 500 * 500.

    但是,假如我们这样去书写。

    <canvas style="width:500px;height:500px;">

    这样实际是把 canvas 默认的 300 * 150 的图片强行拉伸为 500px * 500px 了,所以这样会导致我们的内容被强行缩放,从而导致问题。

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>Document</title>
     <style type="text/css">
      html,body{
       margin: 0px;
      }
      canvas{
       background: #ccc;
      }
     </style>
    </head>
    <body>
     <canvas id="canvas_1">
      我们在设置 canvas 之前需要首先监测用户电脑是否支持 canvas
     </canvas>
    </body>
    <script type="text/javascript">
     var canvas_1 = document.getElementById("canvas_1");
     // 设置宽度和高度,但是这种写法会造成额外的问题
     // 画布会拉伸
     // canvas_1.style.width = "500px";
     // canvas_1.style.height = "500px";
    
     // 所以推荐写法
     // 1.使用内联样式表
     // 2.去使用点(.)
     canvas_1.width = "500"; //注意,不要加 px
     canvas_1.height = "500";
    
    </script>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2.3 获取绘制环境

    我们在上面已经设置了我们的画布的大小,但是存在一个问题。

    我们还没有找到我们的画布呀!~

    要是我们连具体的画布都没有,我们又该向哪里去绘画呢?

    实际上我们可以通过 var ctx = canvas_1.getContext("2d"); 来去获取到我们的绘制环境。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <canvas id="canvas_1" width="500" height="400" style="box-shadow: 0 0 20px black;">
            当前浏览器不支持 canvas
        </canvas>
    </body>
    <script type="text/javascript">
    
        // 获取 canvas 元素对应的 DOM 对象
        var canvas_1 = document.getElementById("canvas_1");
    
        // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
        var ctx = canvas_1.getContext("2d");
    
        // 打印一下,查看是否能够显示具体环境
        console.log(ctx);
    
    </script>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    假如打印成功,我们应该可以在浏览器中的 console 中查看到我们的画布具体信息。

    3.png

    但是请注意,getContext("2d"); 中一定是2d而不是2D,否则不会生效。

    2.4 绘制的坐标轴

    既然我们已经能够获取到我们具体的画布了,那我们是不是开始绘制了呀。

    先等等,我们首先先来分析一个问题,就是我们绘制图形的时候,以这个一个区域,我们应该从哪里开始,设置的数值又应该从哪里开始呢?这时候你就应该去想一想,是不是存在这么一个坐标轴,可以根据这个坐标轴来书写我们的数值呢?

    Paste_Image.png

    请注意,横轴向右是正,纵轴向下是正

    2.5 绘制直线

    我们既然要画一条直线,我们是不是至少应该有这么几个条件呢?

    • 线的起点
    • 线的终点
    • 线的颜色
    • 线的宽度

    所以我们接下来,就需要开始我们的代码书写了。

    我们该如何去进行绘制呢?

    我们需要一些工具,需要具体的方法。

    方法 说明
    beginPath() 开始定义路径
    closePath() 关闭前面定义的路径
    moveTo(float x,float y) 把 canvas 的当前路径的结束点移动到 x, y 对应的点
    lineTo(float x,float y) 把 canvas 的当前路径从当前结束点连接到 x , y 对应的点

    需要注意,moveTo 可以简单理解为,把当前绘制图像的起点设置为某一特定坐标,而 lineTo 则是将当前的起点和你想要设置的那个点之间连接起来。

    而 beginPath 是表示开始定义路径,不会产生特殊的效果。而 closePath 除了表示关闭当前定义的路径之外,还会有一个特殊的作用,就是可以将当前绘制图形的最后一个点和我们绘制图形开始的点进行连接,这一点咱们在章节2.6 中详细去看一下。当然,如果你只需要画一条线,不去加beginPath 和 closep 你的内容实际也是可以出来的,但是推荐加上。

    这个时候我们可以来运行一下,看看效果是否能够出来。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div>
            <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
                当前浏览器不支持 canvas
            </canvas>
        </div>
    </body>
    <script type="text/javascript">
        // 获取 canvas 元素对应的 DOM 对象
        var canvas_1 = document.getElementById("canvas_1");
    
        // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
        var ctx = canvas_1.getContext("2d");
    
        // 打印一下,查看是否能够显示具体环境
        console.log(ctx);
    
        // 开始绘制
        ctx.beginPath();
    
        //设置绘制起点
        ctx.moveTo(0,0);
    
        //设置绘制下一个点
        ctx.lineTo(700,400);
    
        //结束绘制
        ctx.closePath();
    
    </script>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    发现了什么?我们的图形什么都没有出来呀,鹏哥你是不是坑我们呀?

    怎么可能,我那么帅气。

    效果没出来,只是因为 你已经把你的画笔的颜料,要画什么样的线条,全部都想好了,可是你往你的画布上绘画了么?

    没有对吧,所以咯,我们还需要有其他的方法去进行配合。

    - -
    fill() 填充 canvas 当前路径
    stroke() 填充 canvas 当前路径绘制边框

    这个时候我们添加上我们的 stroke() 之后,我们就发现我们的线条出现了。

    可是这条线一直是灰色的呀,好丑,我们想要自己去修改我们的线,该怎么做呢?

    - -
    fillStyle() 设置填充 canvas 路径所使用的填充风格
    strokeStyle() 设置绘制 canvas 路径的填充风格

    他们两个都支持三个属性值。

    1. 符合颜色格式的字符串值,表示使用纯色填充
    2. CanvasGradient,表明使用渐变填充
    3. CanvasPattern,表明使用位图填充

    这几个值,咱们在后续的课程中会去详细说明,在当前不去做更多阐述。

    除此之外,我们还可以设置一下线的宽度。

    - -
    lineWidth() 设置笔触线条的宽度

    这样我们就可以画出一些我们想要的线条的样式了。

    Paste_Image.png

    2.6 绘制三角形

    我们已经创建了这一条线段,那么我们平常开发中不会仅仅让你去绘制一条线吧,最起码我们需要会绘制出一个小的三角形吧。

    这时候我们就需要再去绘制两条线了。

    怎么去添加线呢?lineTo对吧。

    这个时候我们再去绘制一条线。

        //设置绘制起点
        ctx.moveTo(100,100);
    
        //设置绘制下一个点
        ctx.lineTo(700,400);
    
        //设置绘制下一个点
        ctx.lineTo(400,100);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这时候神奇的事情发生了,我们的三角形直接就出现了,可是我们仅仅绘制了两条线呀。

    Paste_Image.png

    这是因为,我们在绘制图形的时候,是不是设置了一个方法?

    还记得上面对 closePath 的描述么?

        //结束绘制
        ctx.closePath();
    • 1
    • 2

    这时因为当我们结束绘制的,电脑会自动将你设置的线段自动连接起来。

    Paste_Image.png

    这个时候我们应该有两个想法了。

    1. 我们可以用这个特性去做一个长方形或者多边形等。

    2. 我们需要给我们的方块内部设置一个颜色。

    那么我们首先来说一下,如何设置一个背景颜色。

    这时候我们需要使用填充。

        // 设置填充样式
        ctx.fillStyle = "green";
    
        // 填充当前视图
        ctx.fill();
    • 1
    • 2
    • 3
    • 4
    • 5

    这个时候我们就能看见,我们的背景颜色就已经成功填充了。

    Paste_Image.png

    当然,我的审美一直很特立独行,所以各位小伙伴也不要在意太多细节啦,科科。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div>
            <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
                当前浏览器不支持 canvas
            </canvas>
        </div>
    </body>
    <script type="text/javascript">
    
        // 获取 canvas 元素对应的 DOM 对象
        var canvas_1 = document.getElementById("canvas_1");
    
        // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
        var ctx = canvas_1.getContext("2d");
    
        // 打印一下,查看是否能够显示具体环境
        console.log(ctx);
    
        // 开始绘制
        ctx.beginPath();
    
        //设置绘制起点
        ctx.moveTo(100,100);
    
        //设置绘制下一个点
        ctx.lineTo(700,400);
    
        //设置绘制下一个点
        ctx.lineTo(400,100);
    
        //设置绘制下一个点
        ctx.lineTo(600,500);
    
        //结束绘制
        ctx.closePath();
    
        //设置线的宽度
        ctx.lineWidth = 10;
    
        //设置绘制的样式
        ctx.strokeStyle = "red";
    
        //绘制点之间的线路
        ctx.stroke();
    
        // 设置填充样式
        ctx.fillStyle = "green";
    
        // 填充当前视图
        ctx.fill();
    
        // 注意:所有的绘制相应属性全部应该放在 closePath 之前
    
    </script>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    除此之外,还有一个需要注意的点,就是我们现在的图形是不是角度都是非常尖锐的?

    那我们是不是可以把这个效果修改一下,改的圆滑一点呢?

    这时候再来跟大家说另外一个属性。

    - -
    lineJoin 设置返回所创建边角的类型,当两条线交汇时。

    通过这个属性,我们就可以去修改我们图形的拐角的样式了,这个样式里面存在三个属性。需要注意一点,你去设置边角的样式,一定要设置在你的绘制矩形框之前,否则效果是不会出现的。

    - -
    bevel 创建斜角
    round 创建圆角
    miter 默认,创建尖角

    miter.png

    round.png

    bevel.png

    这时候我们的效果就已经全部出现了。

    那么大家可以去尝试制作一下下图的内容。

    Paste_Image.png

    2.7 绘制矩形

    不知道小伙伴们有没有将上面的内容成功设置出来呢?

    如果出来了,我们发现一个非常坑爹的情况,他喵的每设置一次都需要专门去计算这个内容的对应数值么?

    不能这么坑爹吧,所以这个时候我们要去学习另外一个方法。

    - -
    strokeRect(float x,float y,float width,float height) 绘制一个矩形边框
    fillRect(float x,float y,float width,float height) 填充一个矩形边框

    有了这两个方法,我们的矩形绘制就非常方便啦。

    那么我们来尝试一下。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div>
            <h2>绘制矩形</h2>
            <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
                当前浏览器不支持 canvas
            </canvas>
        </div>
    </body>
    <script type="text/javascript">
        // 获取 canvas 元素对应的 DOM 对象
        var canvas_1 = document.getElementById("canvas_1");
    
        // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
        var ctx = canvas_1.getContext("2d");
    
        // 设置填充颜色
        ctx.fillStyle = '#f00';
        // 填充一个矩形
        ctx.fillRect(30,20,120,60);
    
        // 设置填充颜色
        ctx.fillStyle = '#ff0';
        // 填充一个矩形
        ctx.fillRect(80,60,120,60);
    
        // 设置填充颜色
        ctx.strokeStyle = '#00f';
        // 填充一个矩形
        ctx.strokeRect(30,130,120,60);
        // 设置线条宽度
        ctx.lineWidth = 20;
    
        // 设置线条宽度
        ctx.lineJoin = "round";
        // 设置填充颜色
        ctx.strokeStyle = '#0ff';
        // 填充一个矩形
        ctx.strokeRect(80,160,120,60);
    
    
        // 设置线条宽度
        ctx.lineJoin = "bevel";
        // 设置填充颜色
        ctx.strokeStyle = '#f0f';
        // 填充一个矩形
        ctx.strokeRect(130,190,120,60);
    
    
        ctx.storke();
    
    </script>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    Paste_Image.png

    2.8 绘制字符串

    我猜现在很多小伙伴都在想,我们可以绘制线条,可以绘制多边形,还可以绘制矩形了,那么接下来是不是要开始学习绘制圆形呢?

    当然不是,因为绘制圆形设计到的内容比较多,咱们放在下一篇文章中来书写。

    今天咱们就先来看一下,我们该如何去绘制我们的字符串。

    在绘制字符串之前同样需要跟大家说这么几个方法。

    - -
    fillText(String Text, float x, float y, [float maxWidth]) 填充字符串
    strokeText(String Text, float x, float y, [float maxWidth]) 绘制字符串边框

    同时我们既然设置了字符串的内容,我们是不是还需要去对我们字符串的对齐方式什么的去做一做设置呢?

    - -
    textAlign 设置绘制字符串的水平对齐方式(start、end、left、right、center等)
    textBaseAlign 设置绘制字符串的垂直对齐方式(top、hanging、middle、alphabetic、idecgraphic、bottom 等)

    了解了这些具体的方法,那我们再来看一下,我们该如何去设置我们的字符串内容。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div>
            <h2>绘制文字</h2>
            <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
                当前浏览器不支持 canvas
            </canvas>
        </div>
    </body>
    <script type="text/javascript">
        // 获取 canvas 元素对应的 DOM 对象
        var canvas_1 = document.getElementById("canvas_1");
    
        // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
        var ctx = canvas_1.getContext("2d");
    
        ctx.fillStyle = '#00f';
        ctx.font = 'italic 50px 隶书';
        ctx.textBaseline = 'top';
    
        //填充字符串
        ctx.fillText('汪先生真是帅',0,0);
        ctx.strokeStyle = 'f0f';
        ctx.font = 'bold 45px 宋体';
    
        // 绘制字符串的边框
        ctx.strokeText('汪先生我爱你',0,50,200);
    
    </script>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35


    2.9 设置阴影

    我们在之前学习 HTML 的过程中,跟大家说过,我们的阴影可以简单分为两种,盒阴影和文字阴影,那在我们的画布中,是否也存在这么一个东西,能够为我们的文字去设置一个阴影呢?

    当然有,要不我也不会专门去提这个事情,对吧。

    我们学习设置阴影,同样要使用这么几个属性。

    - -
    shadowBlur 设置阴影的模糊程度。该值是一个浮点数,该数值越大,阴影的模糊程度也就越大。
    shadowColor 设置阴影的颜色。
    shadowOffsetX 设置阴影在 X 方向的偏移
    shadowOffsetY 设置阴影在 Y 方向的偏移

    那么我们接下来,一起来看看我们该如何去设置阴影。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div>
            <h2>绘制文字</h2>
            <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
                当前浏览器不支持 canvas
            </canvas>
        </div>
    </body>
    <script type="text/javascript">
        // 获取 canvas 元素对应的 DOM 对象
        var canvas_1 = document.getElementById("canvas_1");
    
        // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象
        var ctx = canvas_1.getContext("2d");
    
        // 设置阴影的模糊程度
        ctx.shadowBlur = 5.6;
    
        // 设置阴影的颜色
        ctx.shadowColor = '#222';
    
        // 设置阴影在 X,Y 方向的偏移
        ctx.shadowOffsetX = 10;
        ctx.shadowOffsetY = -6;
    
        ctx.fillStyle = '#00f';
        ctx.font = 'italic 50px 隶书';
        ctx.textBaseline = 'top';
    
        //填充字符串
        ctx.fillText('汪先生真是帅',0,0);
        ctx.strokeStyle = 'f0f';
        ctx.font = 'bold 45px 宋体';
    
        // 绘制字符串的边框
        ctx.strokeText('汪先生我爱你',0,50,200);
    
    </script>
    </html>
    展开全文
  • 学习HTML5 Canvas这一篇文章就够了

    万次阅读 多人点赞 2017-06-16 20:57:43
    一、canvas简介&amp;amp;lt;canvas&amp;amp;gt; 是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行...

    一、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> 。Chrome和Opera 9+ 也支持 <canvas>

    二、Canvas基本使用

    2.1 <canvas>元素

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

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

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

    ###替换内容

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

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

    用文本替换:

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

    <img> 替换:

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

    结束标签</canvas>不可省

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

    2.2 渲染上下文(Thre Rending Context)

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

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

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

    2.3 检测支持性

    var canvas = document.getElementById('tutorial');
    
    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      // drawing code here
    } else {
      // canvas-unsupported code here
    }
    

    2.4 代码模板

    <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");
          	//开始代码
            
        }
        draw();
    </script>
    </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. strokeRect(x, y, width, height)

      绘制一个矩形的边框

    3. clearRect(x, y, widh, height)

      清除指定的矩形区域,然后这块区域会变的完全透明。

    说明:

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

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

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

    function draw(){
        var canvas = document.getElementById('tutorial');
        if(!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.fillRect(10, 10, 100, 50);  //绘制矩形,填充的默认颜色为黑色
        ctx.strokeRect(10, 70, 100, 50);  //绘制矩形边框
        
    }
    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 绘制线段

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

    4.2 绘制三角形边框

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

    4.3 填充三角形

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(50, 50);
        ctx.lineTo(200, 50);
        ctx.lineTo(200, 200);
       
        ctx.fill(); //填充闭合区域。如果path没有闭合,则fill()会自动闭合路径。
    }
    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   //角度转换成弧度
      
    2. arcTo(x1, y1, x2, y2, radius):

      根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点。

    圆弧案例1:

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

    圆弧案例2:

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.arc(50, 50, 40, 0, Math.PI / 2, false);
        ctx.stroke();
    
        ctx.beginPath();
        ctx.arc(150, 50, 40, 0, -Math.PI / 2, true);
        ctx.closePath();
        ctx.stroke();
    
        ctx.beginPath();
        ctx.arc(50, 150, 40, -Math.PI / 2, Math.PI / 2, false);
        ctx.fill();
    
        ctx.beginPath();
        ctx.arc(150, 150, 40, 0, Math.PI, false);
        ctx.fill();
    
    }
    draw();
    

    圆弧案例3:

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(50, 50);
      	//参数1、2:控制点1坐标   参数3、4:控制点2坐标  参数4:圆弧半径
        ctx.arcTo(200, 50, 200, 200, 100);
        ctx.lineTo(200, 200)
        ctx.stroke();
        
        ctx.beginPath();
        ctx.rect(50, 50, 10, 10);
        ctx.rect(200, 50, 10, 10)
        ctx.rect(200, 200, 10, 10)
        ctx.fill()
    }
    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:结束点坐标

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(10, 200); //起始点
        var cp1x = 40, cp1y = 100;  //控制点
        var x = 200, y = 200; // 结束点
        //绘制二次贝塞尔曲线
        ctx.quadraticCurveTo(cp1x, cp1y, x, y);
        ctx.stroke();
        
        ctx.beginPath();
        ctx.rect(10, 200, 10, 10);
        ctx.rect(cp1x, cp1y, 10, 10);
        ctx.rect(x, y, 10, 10);
        ctx.fill();
        
    }
    draw();
    

    绘制三次贝塞尔曲线

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

    说明:

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

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

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

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(40, 200); //起始点
        var cp1x = 20, cp1y = 100;  //控制点1
        var cp2x = 100, cp2y = 120;  //控制点2
        var x = 200, y = 200; // 结束点
        //绘制二次贝塞尔曲线
        ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
        ctx.stroke();
    
        ctx.beginPath();
        ctx.rect(40, 200, 10, 10);
        ctx.rect(cp1x, cp1y, 10, 10);
        ctx.rect(cp2x, cp2y, 10, 10);
        ctx.rect(x, y, 10, 10);
        ctx.fill();
    
    }
    draw();
    

    五、添加样式和颜色

    ​ 在前面的绘制矩形章节中,只用到了默认的线条和颜色。

    ​ 如果想要给图形上色,有两个重要的属性可以做到。

    1. fillStyle = color

      设置图形的填充颜色

    2. strokeStyle = color

      设置图形轮廓的颜色

    备注:

    1. `color` 可以是表示 `css` 颜色值的字符串、渐变对象或者图案对象。
    2. 默认情况下,线条和填充颜色都是黑色。
    3. 一旦您设置了 `strokeStyle` 或者 `fillStyle` 的值,那么这个新值就会成为新绘制的图形的默认值。如果你要给每个图形上不同的颜色,你需要重新设置 `fillStyle` 或 `strokeStyle` 的值。
    

    fillStyle

    function draw(){
      var canvas = document.getElementById('tutorial');
      if (!canvas.getContext) return;
      var ctx = canvas.getContext("2d");
      for (var i = 0; i < 6; i++){
        for (var j = 0; j < 6; j++){
          ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ',' +
            Math.floor(255 - 42.5 * j) + ',0)';
          ctx.fillRect(j * 50, i * 50, 50, 50);
        }
      }
    }
    draw();
    

    strokeStyle

    <script type="text/javascript">
        function draw(){
            var canvas = document.getElementById('tutorial');
            if (!canvas.getContext) return;
            var ctx = canvas.getContext("2d");
            for (var i = 0; i < 6; i++){
                for (var j = 0; j < 6; j++){
                    ctx.strokeStyle = `rgb(${randomInt(0, 255)},${randomInt(0, 255)},${randomInt(0, 255)})`;
                    ctx.strokeRect(j * 50, i * 50, 40, 40);
                }
            }
        }
        draw();
        /**
         作者:李振超      4 Jun 2017 12:12
         返回随机的 [from, to] 之间的整数(包括from,也包括to)
         */
        function randomInt(from, to){
            return parseInt(Math.random() * (to - from + 1) + from);
        }
    
    </script>
    

    Transparency(透明度)

    globalAlpha = transparencyValue

    ​ 这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。

    globalAlpha 属性在需要绘制大量拥有相同透明度的图形时候相当高效。不过,我认为使用rgba()设置透明度更加好一些。

    line style

    1. lineWidth = value

    线宽。只能是正值。默认是1.0

    起始点和终点的连线为中心,上下各占线宽的一半

    ctx.beginPath();
    ctx.moveTo(10, 10);
    ctx.lineTo(100, 10);
    ctx.lineWidth = 10;
    ctx.stroke();
    
    ctx.beginPath();
    ctx.moveTo(110, 10);
    ctx.lineTo(160, 10)
    ctx.lineWidth = 20;
    ctx.stroke()
    

    ###2. lineCap = type

    线条末端样式。

    共有3个值:

    1. butt:线段末端以方形结束

    2. round:线段末端以圆形结束

    3. square:线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域。

      var lineCaps = ["butt", "round", "square"];
      
      for (var i = 0; i < 3; i++){
          ctx.beginPath();
          ctx.moveTo(20 + 30 * i, 30);
          ctx.lineTo(20 + 30 * i, 100);
          ctx.lineWidth = 20;
          ctx.lineCap = lineCaps[i];
          ctx.stroke();
      }
      
      ctx.beginPath();
      ctx.moveTo(0, 30);
      ctx.lineTo(300, 30);
      
      ctx.moveTo(0, 100);
      ctx.lineTo(300, 100)
      
      ctx.strokeStyle = "red";
      ctx.lineWidth = 1;
      ctx.stroke();
      

    3. lineJoin = type

    同一个path内,设定线条与线条间接合处的样式。

    共有3个值round, bevelmiter

    1. round

      通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。 圆角的半径是线段的宽度。

    2. bevel

      在相连部分的末端填充一个额外的以三角形为底的区域, 每个部分都有各自独立的矩形拐角。

    3. miter(默认)

      通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
    
        var lineJoin = ['round', 'bevel', 'miter'];
        ctx.lineWidth = 20;
    
        for (var i = 0; i < lineJoin.length; i++){
            ctx.lineJoin = lineJoin[i];
            ctx.beginPath();
            ctx.moveTo(50, 50 + i * 50);
            ctx.lineTo(100, 100 + i * 50);
            ctx.lineTo(150, 50 + i * 50);
            ctx.lineTo(200, 100 + i * 50);
            ctx.lineTo(250, 50 + i * 50);
            ctx.stroke();
        }
    
    }
    draw();
    

    4. 虚线

    setLineDash 方法和 lineDashOffset 属性来制定虚线样式. setLineDash 方法接受一个数组,来指定线段与间隙的交替;lineDashOffset属性设置起始偏移量.

    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        
        ctx.setLineDash([20, 5]);  // [实线长度, 间隙长度]
        ctx.lineDashOffset = -0;
        ctx.strokeRect(50, 50, 210, 210);
    }
    draw();
    

    备注:

    getLineDash():返回一个包含当前虚线样式,长度为非负偶数的数组。

    六、绘制文本

    绘制文本的两个方法

    canvas 提供了两种方法来渲染文本:

    1. fillText(text, x, y [, maxWidth])

      在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.

    2. strokeText(text, x, y [, maxWidth])

      在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.

    var ctx;
    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        ctx = canvas.getContext("2d");
        ctx.font = "100px sans-serif"
        ctx.fillText("天若有情", 10, 100);
        ctx.strokeText("天若有情", 10, 200)
    }
    draw();
    

    给文本添加样式

    1. font = value

      当前我们用来绘制文本的样式。这个字符串使用和 CSS font属性相同的语法. 默认的字体是 10px sans-serif

    2. textAlign = value

      文本对齐选项. 可选的值包括:start, end, left, right or center. 默认值是 start

    3. textBaseline = value

      基线对齐选项,可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。

    4. direction = value

      文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。

    七、绘制图片

    ​ 我们也可以在canvas上直接绘制图片。

    7.1 由零开始创建图片

    创建<img>元素

    var img = new Image();   // 创建一个<img>元素
    img.src = 'myImage.png'; // 设置图片源地址
    

    脚本执行后图片开始装载

    绘制img

    //参数1:要绘制的img  参数2、3:绘制的img在canvas中的坐标
    ctx.drawImage(img,0,0); 
    

    注意:

    ​ 考虑到图片是从网络加载,如果 drawImage 的时候图片还没有完全加载完成,则什么都不做,个别浏览器会抛异常。所以我们应该保证在 img 绘制完成之后再 drawImage

    var img = new Image();   // 创建img元素
    img.onload = function(){
      ctx.drawImage(img, 0, 0)
    }
    img.src = 'myImage.png'; // 设置图片源地址
    

    7.2 绘制 img 标签元素中的图片

    img 可以 new 也可以来源于我们页面的 <img>标签

    <img src="./美女.jpg" alt="" width="300"><br>
    <canvas id="tutorial" width="600" height="400"></canvas>
    <script type="text/javascript">
        function draw(){
            var canvas = document.getElementById('tutorial');
            if (!canvas.getContext) return;
            var ctx = canvas.getContext("2d");
            var img = document.querySelector("img");
            ctx.drawImage(img, 0, 0);
        }
        document.querySelector("img").onclick = function (){
            draw();
        }
    
    </script>
    

    第一张图片就是页面中的<img>标签

    7.3 缩放图片

    drawImage() 也可以再添加两个参数:

    drawImage(image, x, y, width, height)

    ​ 这个方法多了2个参数:widthheight,这两个参数用来控制 当像canvas画入时应该缩放的大小。

    ctx.drawImage(img, 0, 0, 400, 200)
    

    7.4 切片(slice)

    drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

    ​ 第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。

    其他8个参数:

    ​ 前4个是定义图像源的切片位置和大小,

    ​ 后4个则是定义切片的目标显示位置和大小。

    八、状态的保存和恢复

    Saving and restoring state是绘制复杂图形时必不可少的操作。

    save()和restore()

    saverestore 方法是用来保存和恢复 canvas 状态的,都没有参数。

    Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

    1. 关于 save()

      Canvas状态存储在栈中,每当save()方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:

    • 当前应用的变形(即移动,旋转和缩放)

    • strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值

    • 当前的裁切路径(clipping path

      可以调用任意多次 save方法。(类似数组的push())

    1. 关于restore()

      每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。(类似数组的pop())

    var ctx;
    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
    
        ctx.fillRect(0, 0, 150, 150);   // 使用默认设置绘制一个矩形
        ctx.save();                  // 保存默认状态
    
        ctx.fillStyle = 'red'       // 在原有配置基础上对颜色做改变
        ctx.fillRect(15, 15, 120, 120); // 使用新的设置绘制一个矩形
    
        ctx.save();                  // 保存当前状态
        ctx.fillStyle = '#FFF'       // 再次改变颜色配置
        ctx.fillRect(30, 30, 90, 90);   // 使用新的配置绘制一个矩形
    
        ctx.restore();               // 重新加载之前的颜色状态
        ctx.fillRect(45, 45, 60, 60);   // 使用上一次的配置绘制一个矩形
    
        ctx.restore();               // 加载默认颜色配置
        ctx.fillRect(60, 60, 30, 30);   // 使用加载的配置绘制一个矩形
    }
    draw();
    

    九、变形

    9.1 translate

    translate(x, y)

    ​ 用来移动 canvas原点到指定的位置

    translate方法接受两个参数。x 是左右偏移量,y 是上下偏移量,如右图所示。

    在做变形之前先保存状态是一个良好的习惯。大多数情况下,调用 restore 方法比手动恢复原先的状态要简单得多。又如果你是在一个循环中做位移但没有保存和恢复canvas 的状态,很可能到最后会发现怎么有些东西不见了,那是因为它很可能已经超出 canvas 范围以外了。

    ​ 注意:translate移动的是canvas的坐标原点。(坐标变换)

    var ctx;
    function draw(){
        var canvas = document.getElementById('tutorial1');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.save(); //保存坐原点平移之前的状态
        ctx.translate(100, 100);
        ctx.strokeRect(0, 0, 100, 100)
        ctx.restore(); //恢复到最初状态
        ctx.translate(220, 220);
        ctx.fillRect(0, 0, 100, 100)
    }
    draw();
    

    9.2 rotate

    rotate(angle)

    ​ 旋转坐标轴。

    ​ 这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。

    ​ 旋转的中心是坐标原点。

    var ctx;
    function draw(){
      var canvas = document.getElementById('tutorial1');
      if (!canvas.getContext) return;
      var ctx = canvas.getContext("2d");
    
      ctx.fillStyle = "red";
      ctx.save();
    
      ctx.translate(100, 100);
      ctx.rotate(Math.PI / 180 * 45);
      ctx.fillStyle = "blue";
      ctx.fillRect(0, 0, 100, 100);
      ctx.restore();
    
      ctx.save();
      ctx.translate(0, 0);
      ctx.fillRect(0, 0, 50, 50)
      ctx.restore();
    }
    draw();
    

    9.3 scale

    scale(x, y)

    ​ 我们用它来增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。

    scale方法接受两个参数。x,y分别是横轴和纵轴的缩放因子,它们都必须是正值。值比 1.0 小表示缩 小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。

    ​ 默认情况下,canvas 的 1 单位就是 1 个像素。举例说,如果我们设置缩放因子是 0.5,1 个单位就变成对应 0.5 个像素,这样绘制出来的形状就会是原先的一半。同理,设置为 2.0 时,1 个单位就对应变成了 2 像素,绘制的结果就是图形放大了 2 倍。

    9.4 transform(变形矩阵)

    transform(a, b, c, d, e, f)

    a (m11)

    ​ Horizontal scaling.

    b (m12)

    ​ Horizontal skewing.

    c (m21)

    ​ Vertical skewing.

    d (m22)

    ​ Vertical scaling.

    e (dx)

    ​ Horizontal moving.

    f (dy)

    ​ Vertical moving.

    var ctx;
    function draw(){
        var canvas = document.getElementById('tutorial1');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.transform(1, 1, 0, 1, 0, 0);
        ctx.fillRect(0, 0, 100, 100);
    }
    draw();
    

    十、合成

    ​ 在前面的所有例子中、,我们总是将一个图形画在另一个之上,对于其他更多的情况,仅仅这样是远远不够的。比如,对合成的图形来说,绘制顺序会有限制。不过,我们可以利用 globalCompositeOperation 属性来改变这种状况。

    globalCompositeOperation = type

        var ctx;
        function draw(){
            var canvas = document.getElementById('tutorial1');
            if (!canvas.getContext) return;
            var ctx = canvas.getContext("2d");
            
            ctx.fillStyle = "blue";
            ctx.fillRect(0, 0, 200, 200);
    
            ctx.globalCompositeOperation = "source-over"; //全局合成操作
            ctx.fillStyle = "red";
            ctx.fillRect(100, 100, 200, 200);
        }
        draw();
    
    </script>
    

    注:下面的展示中,蓝色是原有的,红色是新的。

    type `是下面 13 种字符串值之一:

    ##1. source-over(default)

    这是默认设置,新图像会覆盖在原有图像。

    ##2. source-in

    仅仅会出现新图像与原来图像重叠的部分,其他区域都变成透明的。(包括其他的老图像区域也会透明)

    ##3. source-out

    仅仅显示新图像与老图像没有重叠的部分,其余部分全部透明。(老图像也不显示)

    ##4. source-atop

    新图像仅仅显示与老图像重叠区域。老图像仍然可以显示。

    ##5. destination-over

    新图像会在老图像的下面。

    ##6. destination-in

    仅仅新老图像重叠部分的老图像被显示,其他区域全部透明。

    ##7. destination-out

    仅仅老图像与新图像没有重叠的部分。 注意显示的是老图像的部分区域。

    ##8. destination-atop

    老图像仅仅仅仅显示重叠部分,新图像会显示在老图像的下面。

    ##9. lighter

    新老图像都显示,但是重叠区域的颜色做加处理

    ##10. darken

    保留重叠部分最黑的像素。(每个颜色位进行比较,得到最小的)

    blue: #0000ff

    red: #ff0000

    所以重叠部分的颜色:#000000

    ##11. lighten

    保证重叠部分最量的像素。(每个颜色位进行比较,得到最大的)

    blue: #0000ff

    red: #ff0000

    所以重叠部分的颜色:#ff00ff

    ##12. xor

    重叠部分会变成透明

    ##13. copy

    只有新图像会被保留,其余的全部被清除(边透明)

    #十一、裁剪路径

    clip()

    ​ 把已经创建的路径转换成裁剪路径。

    ​ 裁剪路径的作用是遮罩。只显示裁剪路径内的区域,裁剪路径外的区域会被隐藏。

    ​ 注意:clip()只能遮罩在这个方法调用之后绘制的图像,如果是clip()方法调用之前绘制的图像,则无法实现遮罩。

    var ctx;
    function draw(){
        var canvas = document.getElementById('tutorial1');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
    
        ctx.beginPath();
        ctx.arc(20,20, 100, 0, Math.PI * 2);
        ctx.clip();
        
        ctx.fillStyle = "pink";
        ctx.fillRect(20, 20, 100,100);
    }
    draw();
    

    十二、动画

    动画的基本步骤

    1. 清空canvas

      再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是clearRect()方法

    2. 保存canvas状态

      如果在绘制的过程中会更改canvas的状态(颜色、移动了坐标原点等),又在绘制每一帧时都是原始状态的话,则最好保存下canvas的状态

    3. 绘制动画图形

      这一步才是真正的绘制动画帧

    4. 恢复canvas状态

      如果你前面保存了canvas状态,则应该在绘制完成一帧之后恢复canvas状态。

    控制动画

    我们可用通过canvas的方法或者自定义的方法把图像会知道到canvas上。正常情况,我们能看到绘制的结果是在脚本执行结束之后。例如,我们不可能在一个 for 循环内部完成动画。

    也就是,为了执行动画,我们需要一些可以定时执行重绘的方法。

    一般用到下面三个方法:

    1. setInterval()
    2. setTimeout()
    3. requestAnimationFrame()

    ##案例1:太阳系

    let sun;
    let earth;
    let moon;
    let ctx;
    function init(){
        sun = new Image();
        earth = new Image();
        moon = new Image();
        sun.src = "sun.png";
        earth.src = "earth.png";
        moon.src = "moon.png";
    
        let canvas = document.querySelector("#solar");
        ctx = canvas.getContext("2d");
    
        sun.onload = function (){
            draw()
        }
    
    }
    init();
    function draw(){
        ctx.clearRect(0, 0, 300, 300); //清空所有的内容
        /*绘制 太阳*/
        ctx.drawImage(sun, 0, 0, 300, 300);
    
        ctx.save();
        ctx.translate(150, 150);
    
        //绘制earth轨道
        ctx.beginPath();
        ctx.strokeStyle = "rgba(255,255,0,0.5)";
        ctx.arc(0, 0, 100, 0, 2 * Math.PI)
        ctx.stroke()
    
        let time = new Date();
        //绘制地球
        ctx.rotate(2 * Math.PI / 60 * time.getSeconds() + 2 * Math.PI / 60000 * time.getMilliseconds())
        ctx.translate(100, 0);
        ctx.drawImage(earth, -12, -12)
    
        //绘制月球轨道
        ctx.beginPath();
        ctx.strokeStyle = "rgba(255,255,255,.3)";
        ctx.arc(0, 0, 40, 0, 2 * Math.PI);
        ctx.stroke();
    
        //绘制月球
        ctx.rotate(2 * Math.PI / 6 * time.getSeconds() + 2 * Math.PI / 6000 * time.getMilliseconds());
        ctx.translate(40, 0);
        ctx.drawImage(moon, -3.5, -3.5);
        ctx.restore();
    
        requestAnimationFrame(draw);
    }
    

    ##案例2:模拟时钟

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            body {
                padding: 0;
                margin: 0;
                background-color: rgba(0, 0, 0, 0.1)
            }
            
            canvas {
                display: block;
                margin: 200px auto;
            }
        </style>
    </head>
    <body>
    <canvas id="solar" width="300" height="300"></canvas>
    <script>
        init();
    
        function init(){
            let canvas = document.querySelector("#solar");
            let ctx = canvas.getContext("2d");
            draw(ctx);
        }
    
        function draw(ctx){
            requestAnimationFrame(function step(){
                drawDial(ctx); //绘制表盘
                drawAllHands(ctx); //绘制时分秒针
                requestAnimationFrame(step);
            });
        }
        /*绘制时分秒针*/
        function drawAllHands(ctx){
            let time = new Date();
    
            let s = time.getSeconds();
            let m = time.getMinutes();
            let h = time.getHours();
            
            let pi = Math.PI;
            let secondAngle = pi / 180 * 6 * s;  //计算出来s针的弧度
            let minuteAngle = pi / 180 * 6 * m + secondAngle / 60;  //计算出来分针的弧度
            let hourAngle = pi / 180 * 30 * h + minuteAngle / 12;  //计算出来时针的弧度
    
            drawHand(hourAngle, 60, 6, "red", ctx);  //绘制时针
            drawHand(minuteAngle, 106, 4, "green", ctx);  //绘制分针
            drawHand(secondAngle, 129, 2, "blue", ctx);  //绘制秒针
        }
        /*绘制时针、或分针、或秒针
         * 参数1:要绘制的针的角度
         * 参数2:要绘制的针的长度
         * 参数3:要绘制的针的宽度
         * 参数4:要绘制的针的颜色
         * 参数4:ctx
         * */
        function drawHand(angle, len, width, color, ctx){
            ctx.save();
            ctx.translate(150, 150); //把坐标轴的远点平移到原来的中心
            ctx.rotate(-Math.PI / 2 + angle);  //旋转坐标轴。 x轴就是针的角度
            ctx.beginPath();
            ctx.moveTo(-4, 0);
            ctx.lineTo(len, 0);  // 沿着x轴绘制针
            ctx.lineWidth = width;
            ctx.strokeStyle = color;
            ctx.lineCap = "round";
            ctx.stroke();
            ctx.closePath();
            ctx.restore();
        }
        
        /*绘制表盘*/
        function drawDial(ctx){
            let pi = Math.PI;
            
            ctx.clearRect(0, 0, 300, 300); //清除所有内容
            ctx.save();
    
            ctx.translate(150, 150); //一定坐标原点到原来的中心
            ctx.beginPath();
            ctx.arc(0, 0, 148, 0, 2 * pi); //绘制圆周
            ctx.stroke();
            ctx.closePath();
    
            for (let i = 0; i < 60; i++){//绘制刻度。
                ctx.save();
                ctx.rotate(-pi / 2 + i * pi / 30);  //旋转坐标轴。坐标轴x的正方形从 向上开始算起
                ctx.beginPath();
                ctx.moveTo(110, 0);
                ctx.lineTo(140, 0);
                ctx.lineWidth = i % 5 ? 2 : 4;
                ctx.strokeStyle = i % 5 ? "blue" : "red";
                ctx.stroke();
                ctx.closePath();
                ctx.restore();
            }
            ctx.restore();
        }
    </script>
    </body>
    </html>
    

    展开全文
  • HTML5Canvas绘图(上)

    千次阅读 2018-11-26 15:35:11
    1.Canvas绘制步骤 在html5页面中添加canvas元素,定义id属性值以便后面调用  &lt;canvas id="myCanvas" width="500" height="200"&gt;&lt;/canvas&gt; 使用id寻找...

    1.Canvas绘制步骤

    • 在html5页面中添加canvas元素,定义id属性值以便后面调用

               <canvas id="myCanvas" width="500" height="200"></canvas>

    • 使用id寻找页面中的canvas元素

              var c=document.getElementById("myCanvas");

    • 通过canvas元素的getContext方法来获取其上下文(Context),即创建context对象,以获取允许绘制的2D环境

              var context=c.getContext("2d");

    • 使用javascript脚本来进行绘制

             context.fillStyle="#ff0000";

             context.fillRect(50,25,100,50);

    <head>
    	<title></title>
    	<!--给画布设置一个样式-->
    	<style type="text/css">
    		#myCanvas{
    			border: 1px solid blue;
    		}
    	</style>
    	<script type="text/javascript">
    		window.onload=function(){
    			var canvas=document.getElementById("myCanvas");
    			var context=canvas.getContext("2d");
    			context.fillStyle="#ff0000";
    			context.fillRect(50,25,100,50);
    			//距离画布左边50,上边25,绘制的图形宽100,高50
    		}
    	</script>
    </head>
    <body>
        <canvas id="myCanvas" width="500" height="200"></canvas> 
    </body>

    运行结果:

     2.绘制直线相关方法及属性

    方法:

    • beginPath():定义绘制动作的开始
    • moveTo():绘制图形的起点位置
    • lineTo():绘制图形的重点位置
    • stroke():为所画的线赋予颜色,如没有指定,默认为黑色

    属性:

    • lineWidth:直线的宽度
    • strokeStvle:直线的颜色
    • 直线端点样式:用lineCap属性设定,包括三种样式,分别为butt,round,square
    <html>
    <title></title>
    	<style type="text/css">
    		#myCanvas{
    			border: 1px solid blue;
    			background-color: #77ffcc;
    		}
    	</style>
    	<script type="text/javascript">
    		window.onload=function(){
    			var canvas=document.getElementById("myCanvas");
    			var context=canvas.getContext("2d");
    			//绘制直线
    			context.beginPath();
    			context.moveTo(50,100);
    			context.lineTo(200,100);
    			context.lineWidth=10;
    			context.strokeStyle="#ff0000";
    			context.lineCap="round";
    			context.stroke();	
    		}
    	</script>
    </head>
    <body>
        <canvas id="myCanvas" width="500" height="200"></canvas> 
    </body>
    </html>

    3.绘制弧线和曲线  

              arcTo(x1,y1,x2,y2,radius) ;包含五个参数,(x1,y1)是端点1,(x2,y2)是端点2,radius是绘制的弧线的半径,此方法就是利用第一条线的终点、端点1、端点2组成的夹角,与夹角两边相切并以radius为半径画弧线,详情实例见下面代码。

    <html>
    <title></title>
    	<style type="text/css">
    		#myCanvas{
    			border: 1px solid blue;
    			background-color: #77ffcc;
    		}
    	</style>
    	<script type="text/javascript">
    		window.onload=function(){
    			var canvas=document.getElementById("myCanvas");
    			var context=canvas.getContext("2d");
    			//绘制弧线
    			context.beginPath();
    			context.moveTo(20,20);//第一条直线的起点
    			context.lineTo(100,20);//第一条直线的终点
    			//端点1:(150,20)端点2:(150,70)b半径:50;
    			context.arcTo(150,20,150,70,50);
    			context.lineTo(150,120);//第二条线的终点
    			context.stroke();	
    		}
    	</script>
    </head>
    <body>
        <canvas id="myCanvas" width="500" height="200"></canvas> 
    </body>

    •  arcTo():创建介于两个切线之间的弧/曲线
    • quadraticCurveTo():绘制二次曲线,每条二次曲线由上下文点、一个控制点和一个终止点来定义
    <html>
    	<style type="text/css">
    		#myCanvas{
    			border: 1px solid blue;
    			background-color: #77ffcc;
    		}
    	</style>
    	<script type="text/javascript">
    		window.onload=function(){
    			var canvas=document.getElementById("myCanvas");
    			var context=canvas.getContext("2d");
    			//绘制二次贝塞尔曲线
    			context.beginPath();
    			context.moveTo(200,100);//起始点
    			context.quadraticCurveTo(288,0,388,150);
    			context.lineWidth=5;
    			context.strokeStyle="pink";
    			context.stroke();	
    		}
    	</script>
    </head>
    <body>
        <canvas id="myCanvas" width="500" height="200"></canvas> 
    </body>
    </html>

     

    • bezierCurveTo():绘制贝塞尔曲线,每条贝塞尔曲线由上下文点、两个控制点和一个终止点来确定

     

    展开全文
  • Canvas简明教程(完整源码)

    千次阅读 2017-12-25 11:28:37
    博客停更大半年,趁着圣诞更新了个人主页,顺便推一篇很乱的文章上来哈哈哈哈哈哈哈!!! 主页效果:anxpp.com原文出处:http://blog.anxpp.com/index.php/archives/1094/原文...Canvas简明教程<canvas> 是 HTML5 新
    博客停更大半年,趁着圣诞更新了个人主页,顺便推一篇很乱的文章上来哈哈哈哈哈哈哈!!!
    

    主页效果:anxpp.com

    原文出处:http://blog.anxpp.com/index.php/archives/1094/

    原文出处:http://blog.csdn.net/anxpp/article/details/78890819

    By anxpp
    

    Canvas简明教程

    <canvas> 是 HTML5 新增的元素,可用于通过使用 JavaScript 中的脚本来绘制图形。例如,它可以用于绘制图形,制作照片,创建动画,甚至可以进行实时视频处理或渲染。
    
    本例包含个人主页全部源码。
    

    浏览器兼容:

    元素 chrome IE firefox Safari
    Canvas 4.0+ 9.0+ 2.0+ 3.1+

    Canvas 能干什么

    • 图表
    • 小游戏
    • 活动页
    • 特效
    • 背景等

    获取 Canvas 对象

    方法:
    - canvas.getContext(contextType, contextAttributes);

    通常我们在创建好一个 Canvas 标签的时候,我们要做的第一步就是要先获取到这个 Canvas 的上下文昌对象。

    上下文类型(contextType):
    - 2d(本小册所有的示例都是 2d 的):代表一个二维渲染上下文
    - webgl(或”experimental-webgl”):代表一个三维渲染上下文
    - webgl2(或”experimental-webgl2”):代表一个三维渲染上下文;这种情况下只能在浏览器实现 WebGL 版本2 (OpenGL ES 3.0)。

    绘制路径

    请结合源码查看效果
    

    方法列表

    熟悉有些什么方法,能做什么即可
    
    方法 描述
    fill() 填充路径
    stroke() 描边
    arc() 创建圆弧
    rect() 创建矩形
    fillRect() 绘制矩形路径区域
    strokeRect() 绘制矩形路径描边
    clearRect() 在给定的矩形内清除指定的像素
    arcTo() 创建两切线之间的弧/曲线
    beginPath() 起始一条路径,或重置当前路径
    moveTo() 把路径移动到画布中的指定点,不创建线条
    lineTo() 添加一个新点,然后在画布中创建从该点到最后指定点的线条
    closePath() 创建从当前点回到起始点的路径
    clip() 从原始画布剪切任意形状和尺寸的区域
    quadraticCurveTo() 创建二次方贝塞尔曲线
    bezierCurveTo() 创建三次方贝塞尔曲线
    isPointInPath() 如果指定的点位于当前路径中,则返回 true,否则返回 false

    方法介绍

    该部分可以跳过,当参考手册即可。
    

    arc() 方法:创建弧/曲线(用于创建圆或部分圆)

    context.arc(x,y,r,sAngle,eAngle,counterclockwise);

    • x:圆的中心的 x 坐标。
    • y:圆的中心的 y 坐标。
    • r:圆的半径
    • sAngle:起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
    • eAngle:结束角,以弧度计。
    • counterclockwise:可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。

    moveTo(x,y):把路径移动到画布中的指定点,不创建线条

    lineTo(x,y):添加一个新点,然后在画布中创建从该点到最后指定点的线条

    样式:
    - lineCap | 设置或返回线条的结束端点样式
    - lineJoin | 设置或返回两条线相交时,所创建的拐角类型
    - lineWidth | 设置或返回当前的线条宽度
    - miterLimit | 设置或返回最大斜接长度

    fillRect(x,y,width,heighr):绘制一个实心矩形

    strokeRect(x,y,width,height):绘制一个空心矩形

    画一个点

        var canvas4 = document.getElementById("canvas4");
        var context4 = canvas4.getContext("2d");
        canvas4.width = 400;
        canvas4.height = 400;
        context4.beginPath();
        context4.arc(100, 100, 1, 0, Math.PI * 2, true);
        context4.closePath();
        context4.fillStyle = 'rgb(255,255,255)';
        context4.fill();

    绘制弧/曲线

        var canvas5 = document.getElementById("canvas5");
        var context5 = canvas5.getContext("2d");
        canvas5.width = 400;
        canvas5.height = 400;
        context5.beginPath();
        context5.arc(100, 100, 50, 0, Math.PI * 0.5, false);
        context5.strokeStyle = "white";
        context5.stroke();

    绘制线条

    • 直线:
        var canvas6 = document.getElementById("canvas6");
        var context6 = canvas6.getContext("2d");
        canvas6.width = 400;
        canvas6.height = 400;
        context6.beginPath();
        context6.moveTo(50,50);
        context6.lineTo(100,100);
        context6.strokeStyle = '#fff';
        context6.stroke();
    • 折线:
        var canvas7 = document.getElementById("canvas7");
        var context7 = canvas7.getContext("2d");
        canvas7.width = 400;
        canvas7.height = 400;
        context7.beginPath();
        context7.lineTo(200, 200);
        context7.lineTo(200, 100);
        context7.lineTo(100, 50);
        context7.strokeStyle = '#fff';
        context7.stroke();
    • 添加样式
        var canvas8 = document.getElementById("canvas8");
        var context8 = canvas8.getContext("2d");
        canvas8.width = 400;
        canvas8.height = 400;
        context8.beginPath();
        context8.moveTo(10,10);
        context8.lineTo(100,100);
        context8.lineWidth = 10;
        context8.lineCap = 'round';
        context8.strokeStyle = '#fff';
        context8.stroke()

    绘制矩形

        var canvas9 = document.getElementById("canvas9");
        var context9 = canvas9.getContext("2d");
        canvas9.width = 400;
        canvas9.height = 400;
        context9.beginPath();
        context9.fillStyle = '#fff';
        context9.fillRect(10, 10, 100, 100);
        context9.strokeStyle = '#fff';
        context9.strokeRect(130, 10, 100, 100);

    颜色、样式和阴影

    • fillStyle | 设置或返回用于填充绘画的颜色、渐变或模式
    • strokeStyle | 设置或返回用于笔触的颜色、渐变或模式
    • shadowColor | 设置或返回用于阴影的颜色
    • shadowBlur | 设置或返回用于阴影的模糊级别
    • shadowOffsetX | 设置或返回阴影距形状的水平距离
    • shadowOffsetY | 设置或返回阴影距形状的垂直距离

    阴影

        var canvas10 = document.getElementById("canvas10");
        var context10 = canvas10.getContext("2d");
        canvas10.width = 400;
        canvas10.height = 400;
        context10.beginPath();
        context10.arc(100,100,50,0,2*Math.PI,false);
        context10.fillStyle = '#fff';
        context10.shadowBlur = 20;
        context10.shadowColor = '#fff';
        context10.fill()

    渐变

    • createLinearGradient() 创建线性渐变(用在画布内容上)
    • createPattern() 在指定的方向上重复指定的元素
    • createRadialGradient() 创建放射状/环形的渐变(用在画布内容上)
    • addColorStop() 规定渐变对象中的颜色和停止位置

    context.createLinearGradient(x0,y0,x1,y1):

    • x0:开始渐变的 x 坐标
    • y0:开始渐变的 y 坐标
    • x1:结束渐变的 x 坐标
    • y1:结束渐变的 y 坐标

    gradient.addColorStop(stop,color):

    • stop:介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置。
    • color:在结束位置显示的 CSS 颜色值

    粉色到白色的由上向下的渐变:

        var canvas11 = document.getElementById("canvas11");
        var context11 = canvas11.getContext("2d");
        canvas11.width = 400;
        canvas11.height = 400;
        var grd11 = context11.createLinearGradient(100,100,100,200);
        grd11.addColorStop(0,'pink');
        grd11.addColorStop(1,'white');
        context11.fillStyle = grd11;
        context11.fillRect(100,100,200,200);

    彩虹渐变:

        var canvas12 = document.getElementById("canvas12");
        var context12 = canvas12.getContext("2d");
        canvas12.width = 400;
        canvas12.height = 400;
        var grd12 = context12.createLinearGradient(0,0,0,400);
        grd12.addColorStop(0,'rgb(255, 0, 0)');
        grd12.addColorStop(0.2,'rgb(255, 165, 0)');
        grd12.addColorStop(0.3,'rgb(255, 255, 0)');
        grd12.addColorStop(0.5,'rgb(0, 255, 0)');
        grd12.addColorStop(0.7,'rgb(0, 127, 255)');
        grd12.addColorStop(0.9,'rgb(0, 0, 255)');
        grd12.addColorStop(1,'rgb(139, 0, 255)');
        context12.fillStyle = grd12;
        context12.fillRect(0,0,400,400);

    图形转换

    • scale() 缩放当前绘图至更大或更小
    • rotate() 旋转当前绘图
    • translate() 重新映射画布上的 (0,0) 位置
    • transform() 替换绘图的当前转换矩阵
    • setTransform() 将当前转换重置为单位矩阵。然后运行 transform()

    缩放

        var canvas13 = document.getElementById("canvas13");
        var context13 = canvas13.getContext("2d");
        canvas13.width = 400;
        canvas13.height = 400;
        context13.strokeStyle = 'white';
        context13.strokeRect(5, 5, 50, 25);
        context13.scale(2, 2);
        context13.strokeRect(5, 5, 50, 25);
        context13.scale(2, 2);
        context13.strokeRect(5, 5, 50, 25);

    设置 scale() 方法之后在设置的矩形,无论是线条的宽度还是坐标的位置,都被放大了。
    并且 scale() 的效果是可以叠加的,也就是说,我们在上面的例子中使用了两次 scale(2,2)。
    那么,最后一个矩形相对于第一个矩形长和宽,以及坐标的位置就放大了 4 倍。

    旋转

    context.rotate(angle)

    angle : 旋转角度,以弧度计。
    如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算。
    举例:如需旋转 5 度,可规定下面的公式:5*Math.PI/180。

        var canvas14 = document.getElementById("canvas14");
        var context14 = canvas14.getContext("2d");
        canvas14.width = 400;
        canvas14.height = 400;
        context14.fillStyle = 'white';
        context14.rotate(20*Math.PI/180);
        context14.fillRect(70,30,200,100);

    在进行图形变换的时候,需要画布旋转,然后再绘制图形。

    这样的结果是使用的图形变换的方法都是作用在画布上的,既然对画布进行了变换,那么在接下来绘制的图形都会变换。

    比如对画布使用了 rotate(20*Math.PI/180) 方法,就是将画布旋转了 20°,然后之后绘制的图形都会旋转 20°。

    图像绘制

    context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height)

    • img:规定要使用的图像、画布或视频。
    • sx:可选。开始剪切的 x 坐标位置。
    • sy:可选。开始剪切的 y 坐标位置。
    • swidth:可选。被剪切图像的宽度。
    • sheight:可选。被剪切图像的高度。
    • x:在画布上放置图像的 x 坐标位置。
    • y:在画布上放置图像的 y 坐标位置。
    • width:可选。要使用的图像的宽度。(伸展或缩小图像)
    • height:可选。要使用的图像的高度。(伸展或缩小图像)
        document.getElementById("tulip").onload = function () {
            var canvas15 = document.getElementById("canvas15");
            var context15 = canvas15.getContext("2d");
            context15.width = 400;
            context15.height = 400;
            var img = document.getElementById("tulip");
            context15.drawImage(img, 90, 130, 90, 80, 20, 20, 90, 80);
        }

    随机粒子

    • 创建粒子类
    function Round_item(index,x,y) {
            this.index = index;
            this.x = x;
            this.y = y;
            this.r = Math.random() * 2 + 1;
            var alpha = (Math.floor(Math.random() * 10) + 1) / 10 / 2;
            this.color = "rgba(255,255,255," + alpha + ")";
        }
    • 定义粒子
    Round_item.prototype.draw = function () {
            content.fillStyle = this.color;
            content.shadowBlur = this.r * 2;
            content.beginPath();
            content.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
            content.closePath();
            content.fill();
        };
    • 初始化粒子
    function init() {
            for(var i = 0; i < initRoundPopulation; i++ ){
                round[i] = new Round_item(i,Math.random() * WIDTH,Math.random() * HEIGHT);
                round[i].draw();
            }
        }
    • 完整代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>随机粒子</title>
        <style>
            html, body {
                margin: 0;
                overflow: hidden;
                width: 100%;
                height: 100%;
                /*cursor: none;*/
                background: black;
            }
        </style>
    </head>
    <body>
    <canvas id="canvas"></canvas>
    <script>
        var ctx = document.getElementById('canvas'),
            content = ctx.getContext('2d'),
            round = [],
            WIDTH,
            HEIGHT,
            initRoundPopulation = 80;
        WIDTH = document.documentElement.clientWidth;
        HEIGHT = document.documentElement.clientHeight;
    
        ctx.width = WIDTH;
        ctx.height = HEIGHT;
    
        function Round_item(index, x, y) {
            this.index = index;
            this.x = x;
            this.y = y;
            this.r = Math.random() * 2 + 1;
            var alpha = (Math.floor(Math.random() * 10) + 1) / 10 / 2;
            this.color = "rgba(255,255,255," + alpha + ")";
        }
    
        Round_item.prototype.draw = function () {
            content.fillStyle = this.color;
            content.shadowBlur = this.r * 2;
            content.beginPath();
            content.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
            content.closePath();
            content.fill();
        };
    
        function init() {
            for (var i = 0; i < initRoundPopulation; i++) {
                round[i] = new Round_item(i, Math.random() * WIDTH, Math.random() * HEIGHT);
                round[i].draw();
            }
        }
    
        init();
    </script>
    </body>
    </html>

    动起来

    • 定义粒子的运动
        Round_item.prototype.move = function () {
            this.y -= 0.15;
            if (this.y <= -10)
                this.y = HEIGHT + 10;
            this.draw();
        };
    • 添加定时器
        function animate() {
            content.clearRect(0, 0, WIDTH, HEIGHT);
            for (var i in round)
                round[i].move();
            requestAnimationFrame(animate)
        }
    • 完整代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body {
                margin: 0;
                overflow: hidden;
                width: 100%;
                height: 100%;
                /*cursor: none;*/
                background: black;
            }
        </style>
    </head>
    <body>
    <canvas id="canvas"></canvas>
    <script>
        var ctx = document.getElementById('canvas'),
            content = ctx.getContext('2d'),
            round = [],
            WIDTH,
            HEIGHT,
            initRoundPopulation = 200;
    
        WIDTH = document.documentElement.clientWidth;
        HEIGHT = document.documentElement.clientHeight;
    
        ctx.width = WIDTH;
        ctx.height = HEIGHT;
    
        function Round_item(index, x, y) {
            this.index = index;
            this.x = x;
            this.y = y;
            this.r = Math.random() * 2 + 1;
            var alpha = (Math.floor(Math.random() * 10) + 1) / 10 / 2;
            this.color = "rgba(255,255,255," + alpha + ")";
        }
    
        Round_item.prototype.draw = function () {
            content.fillStyle = this.color;
            content.shadowBlur = this.r * 2;
            content.beginPath();
            content.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
            content.closePath();
            content.fill();
        };
    
        function animate() {
            content.clearRect(0, 0, WIDTH, HEIGHT);
            for (var i in round)
                round[i].move();
            requestAnimationFrame(animate)
        }
    
        Round_item.prototype.move = function () {
            this.y -= 0.15;
            if (this.y <= -10)
                this.y = HEIGHT + 10;
            this.draw();
        };
    
        function init() {
            for (var i = 0; i < initRoundPopulation; i++) {
                round[i] = new Round_item(i, Math.random() * WIDTH, Math.random() * HEIGHT);
                round[i].draw();
            }
            animate();
        }
    
        init();
    </script>
    </body>
    </html>

    鼠标

    主要是监听鼠标移动事件:

    window.onmousemove = function (event) {/*...*/}

    其他都差不多了,一分完整的示例代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>鼠标互动</title>
        <style>
            html, body {
                margin: 0;
                overflow: hidden;
                width: 100%;
                height: 100%;
                /*cursor: none;*/
                background: black;
            }
        </style>
    </head>
    <body>
    <canvas id="canvas"></canvas>
    <script>
        var canvas = document.getElementById('canvas'),
            ctx = canvas.getContext('2d'),
            WIDTH = canvas.width = document.documentElement.clientWidth,
            HEIGHT = canvas.height = document.documentElement.clientHeight,
            para = {
                num: 100,
                color: false,    //  颜色  如果是false 则是随机渐变颜色
                r: 0.9,
                o: 0.09,         //  判断圆消失的条件,数值越大,消失的越快
                a: 1
            },
            color,
            color2,
            round_arr = [];
        window.onmousemove = function (event) {
            mouseX = event.clientX;
            mouseY = event.clientY;
            round_arr.push({
                mouseX: mouseX,
                mouseY: mouseY,
                r: para.r,
                o: 1
            })
        };
        // 判断参数中是否设置了 color,如果设置了 color,就使用该值、
        // 如果参数中的 color 为 false,那么就使用随机的颜色
        if (para.color) color2 = para.color;
        else color = Math.random() * 360;
    
        function animate() {
            if (!para.color) {
                color += .1;
                color2 = 'hsl(' + color + ',100%,80%)';
            }
            ctx.clearRect(0, 0, WIDTH, HEIGHT);
            for (var i = 0; i < round_arr.length; i++) {
                ctx.fillStyle = color2;
                ctx.beginPath();
                ctx.arc(round_arr[i].mouseX, round_arr[i].mouseY, round_arr[i].r, 0, Math.PI * 2);
                ctx.closePath();
                ctx.fill();
                round_arr[i].r += para.r;
                round_arr[i].o -= para.o;
                if (round_arr[i].o <= 0) {
                    round_arr.splice(i, 1);
                    i--;
                }
            }
            window.requestAnimationFrame(animate);
        }
        animate();
    </script>
    </body>
    </html>

    GitHub 中 home 目录即为 http://anxpp.com 主页的全部源码

    写得很乱,有待整理~~~

    展开全文
  • 讲一讲 Canvas 究竟是个啥

    千次阅读 2016-12-19 17:55:33
    一个很重要的原因是,Canvas 的标准还没有完全确定,不适合大规模用在生产环境。但是,Canvas 的优点也是很明显的,例如在绘制含有大量元素的图表的时候,SVG 往往因为性能问题而无法胜任,例如我见过的一次技术分享...
  • canvas

    2019-12-18 15:59:06
    canvas本身没有绘制能力,必须使用脚本来完成实际的绘图任务 getContext():方法返回一个对象,该对象提供了用于在画布上绘图的方法和属性 <canvas id="canvas"></canvas> // 定义一个ID名为canvas的...
  • 在实际开发过程中,有时需要将图表或者地图等基于Canvas技术渲染的数据下载到本地保存到情况,下面介绍两种方法来完成这种功能。 一、a 标签法 a 标签方法主要分为以下步骤: 将 canvas 元素的数据通过原生 api ...
  • 什么是Canvas

    2020-02-15 19:35:37
    canvas> 元素 HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。 <canvas> 标签只是图形容器,您必须使用脚本来绘制图形。 getContext() 方法可返回一个对象,该对象提供了...
  • canvas

    2019-06-22 14:13:33
    创建Canvas元素 <cavars with=300px, hight="100px"//画布大小要写在标签内></cavars> 通过JavaScript来绘制 <script> /*获取元素*/ //va...
  • C/C++实现游戏角色移动,实现游戏背景变化,C/C++win32编程。
  • canvas canvas是Android中自定义绘图中特别重要的一部分,如果你想画出想要的图形,canvas操作能帮你轻松许多。 canvas.save()和canvas.restore()  这两个方法是最先应该了解的,save方法是将现在的画布状态...
  • (精华)2020年6月28日 Canvas 动态绘图

    万次阅读 2020-06-28 07:59:25
    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta ...绘制
  • (精华)2020年6月28日 Canvas 基础知识

    万次阅读 2020-06-28 07:55:38
    Canvas绘制线条 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta ...
  • (精华)2020年6月28日 Canvas 元素拖动

    万次阅读 2020-06-28 08:26:55
    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta ...图片绘
  • (精华)2020年6月28日 Canvas 抽奖轮盘

    万次阅读 2020-06-28 08:07:41
    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <...canvas id="canvas" width="500" height="500" style="border: 1px solid black"></canva
  • 1.新建canvas.js // 炫酷渐变色背景粒子线条折线连接canvas动画 export const canvas = (val) => { var requestAnimationFrame = window.requestAnimationFrame || function (callback) { window....
  • 自定义控件之绘图篇(四):canvas变换与操作

    万次阅读 多人点赞 2014-09-05 15:05:36
    前言:前几篇讲解了有关canvas绘图的一些操作,今天更深入一些,讲讲对画布的操作,这篇文章不像前几篇那么容易理解,如果以前没有接触过画布的童鞋可能比较难以理解,为什么会这样。我尽量多画图,让大家更清晰明白...
  • canvas

    千次阅读 2018-09-20 17:12:45
    canvas 只能在标签中用width。heigth修改大小 基本方法: 先得到canvas: let canvas = document.querySelector('#canvas') // 得到canvas let gd = canvas.getContext('2d')//得到canvas上下文环境 gd.moveTo(a,b...
  • canvas绘图工具

    万次阅读 2019-01-21 15:34:36
    关于canvas绘图,在html页面上太方便了。为什么不用SVG呢?SVG大量的操作DOM元素你会发现网页的内存一下就达到几个G非常恐怖,更别说应用到移动端了。百度取了不少经,什么画板涂鸦只是小把戏缺乏实用性,灵活性。...
  • Canvas类的最全面详解 - 自定义View应用系列

    万次阅读 多人点赞 2017-03-06 21:22:06
    Canvas类的使用在自定义View绘制中发挥着非常重要的作用 网上有大量关于自定义View中Canvas类的文章,但存在一些问题:内容不全、思路不清晰、简单问题复杂化等等 今天,我将全面总结自定义View中的Canvas类的使用...

空空如也

1 2 3 4 5 ... 20
收藏数 272,959
精华内容 109,183
关键字:

canvas