canvas初级篇

来源:互联网 发布:阿里云 腾讯云 对比 编辑:程序博客网 时间:2024/05/18 10:17

Canvas基本篇 - 大家一起玩一玩 Canvas

什么是Canvas

就是 HTML 5 给出的一个可以展示绘图内容的标签,最早是 苹果公司 提出的 该标签。
canvas 使用领域 :

  1. 游戏
  2. 可视化数据(重点)
  3. banner 广告
  4. 多媒体
  5. 未来

    • 模拟仿真 threejs.org ( 卖汽车的公司有些用这个做 3d 仿真展示 )

    • 远程操作 万网远程控制貌似有用到

    • 图形编辑 网页版的 ps,很多网站已经提供了绘图的功能

只要不是做游戏,我们一般能做到数据图形化就够了

Canvas 基本使用

  1. 页面新建一个 canvas 标签即可,默认就会占据 300 * 150 的宽高(面试有的会问哦)
  2. 宽高利用 html 属性 来设置宽高注意: 千万不要使用 CSS 来设置。因为:

    • 使用 属性设置 canvas 标签的宽高,实际上相当于增加了 canvas 画布的像素,是真的大了

    • 而通过 css 设置画布大小,是将内容拉伸,不会增加像素点,只是将像素扩大或缩小,甚至会失真

  3. Canvas 只是用于展示 绘图的内容,不能绘图

    绘图需要获得绘图工具,每一个 Canvas 都有自己的一套工具。

    如果绘制 2d 图形,语法 canvas.getContext( ‘2d’ ) 就会返回绘图工具集,这个工具专门绘制 2d平面图形,是个 CanvasRenderingContext2D 对象。

    如果绘制 3d 立体 需要了解 webgl, 语法 canvas.getContext( ‘webgl’ ); 可以获得 WebGLRenderingContext对象,注意低版本可能不支持,这里不做探讨。

  4. 绘图常用方法
    ctx.moveTo(x,y) 方法: 把画笔放在哪里
    ctx.lineTo(x,y) 方法: 从刚才的位置开始 画到哪里
    ctx.stroke(); 描边绘图方法,只有最后描边了才能看到效果,作用:将刚刚绘制的所有的点联系起来,就可以看到图形了

代码案例:

    <canvas width='800' height='1000' id='cas' style='border: 1px solid blue;'></canvas>    <script>        // 不能用 css 设置, css 设置会拉伸,不会提高像素点        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' ); // 获得 CanvasRenderingContext2D 对象        ctx.moveTo( 200, 200 ); // 把笔放到 200 200        ctx.lineTo( 200, 300 ); // 划到 200 300 画一条竖线        ctx.stroke();   // 描边绘图方法,只有最后面描边了才能看到效果,所有的点联系起来    </script>

绘图的坐标系

canvas 中的坐标系 默认是以 canvas 左上角作为原点 (0, 0)

横向 x轴,向右为正,纵向 y轴,向下为正

绘制虚线

虚线怎么绘制,虚线就是一小段一小段的实线。
- 实例:从 (100,100) 绘制虚线 到右下角 ( 500,100 )

        <canvas width='800' height='1000' id='cas' style='border: 1px solid blue;'></canvas>        <script>            var cas = document.getElementById( 'cas' );            var ctx = cas.getContext( '2d' );            // 从 (100,100) 绘制虚线 到右下角 ( 500,100 ),先画一小段            ctx.moveTo( 100, 100 );            ctx.lineTo( 110, 100 );            // 空一段            // 在绘制一段,从 120 开始            ctx.moveTo( 120, 100 );            ctx.lineTo( 130, 100 );            ctx.stroke();   // 描边绘图,所有的点联系起来        </script>

可以看到两段虚线已经出来了。同理,用循环做

       <canvas width='800' height='1000' id='cas' style='border: 1px solid blue;'></canvas>       <script>           var cas = document.getElementById( 'cas' );           var ctx = cas.getContext( '2d' );           var step = 10;  //虚线距离           var start = 100;    // 开始位置           var end = 500;           while( true ) { // 一直绘制下去               if( start > end ) break;    // 大于 end 退出               // 实线部分               ctx.moveTo( start, 100 );               ctx.lineTo( start+=step, 100 );               // 绘制空白部分               start+=step;           }           ctx.stroke(); // 描边绘图,所有的点联系起来       </script>
这样我们虚线就画出来了,当然后面还有更简单的绘制方法,这里作为学习,现在这样的绘制是一种方法。

绘制正方形

绘制正方形需要知道坐标,边长,然后从坐标开始moveTo,一步一步连线lineTo连过去,最后描边绘图stroke联系起来, 非常的简单,正方形就出来了。

案例如下:

    <canvas width='800' height='600' id='cas' style='border: 1px solid blue;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        // 绘制正方形需要知道坐标,边长        // 假定 起点 (100,100) 宽高(边长) 200        ctx.moveTo( 100, 100 );        // 先横向 200        ctx.lineTo( 100 + 200, 100 );        // 在新的位置向下 200        ctx.lineTo( 300, 100 + 200 );        // 向左 200        ctx.lineTo( 300 - 200, 300 );        // 向上 200        ctx.lineTo( 100, 300 - 200 );        ctx.stroke();   // 描边绘图,所有的点联系起来    </script>

同理呢,三角形, 算算坐标不就好了:

    var cas = document.getElementById( 'cas' );    var ctx = cas.getContext( '2d' ); // 获取绘画工具    ctx.moveTo( 100, 100 ); // 开始落笔 左边点    ctx.lineTo( 150, 150 ); // 连线 连到哪里    ctx.lineTo( 200, 100 );    ctx.lineTo( 100, 100 );    ctx.stroke(); // 所有的点联系起来

绘制方法

ctx.stroke( ); 这个方法我们刚才已经用过了, 作用:将刚刚绘制的所有的点联系起来

ctx.fill( ); 填充方法,他会在绘制的形状中进行填充,默认是黑色。如果绘制的时候没有形成一个形状,fill就会将开始的点和结束的点连起来,最后进行填充起来,用法跟 stroke 大同小异。

案例:正方形填充,把前面代码拿过来,最后一句 改成 fill 就好了

    <canvas width='800' height='600' id='cas' style='border: 1px solid blue;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        // 绘制正方形需要知道坐标,边长        // 假定 起点 (100,100) 宽高(边长) 200        ctx.moveTo( 100, 100 );        ctx.lineTo( 100 + 200, 100 );        ctx.lineTo( 300, 100 + 200 );        ctx.lineTo( 300 - 200, 300 );        ctx.lineTo( 100, 300 - 200 );        ctx.fill();   // 描边绘图    </script>

非零环绕原则 ( 理解很重要 )

如果需要判断某个区域是否需要填充颜色,就从该区域外随机的选取一个点,从这个点拉一条直线出来,穿过该图形,一定要拉到图形的外面,与穿过的线组成矢量线,看方向,如果是 顺时针方向,就是 +1,如果是 逆时针就 计为 -1, 看求和的结果, 如果是 0 就准备不填充,如果 非 0,就准备填充。就是非 0 环绕原则。

这是浏览器的渲染解析原则,一定要理解。不理解的可以看下下面的 案例 和 图示。

案例:画一个回字框框,可以用 顺时针的正方形 套 逆时针的 正方形来做,看图解析原理

非0环绕原则

根据图示呢,我们就来画个回形,顺时针套逆时针,最后 ctx.fill( )

    <canvas width='800' height='600' id='cas' style='border: 1px solid blue;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        // 顺时针的正方形        ctx.moveTo( 100, 100 );        ctx.lineTo( 300, 100 );        ctx.lineTo( 300, 300 );        ctx.lineTo( 100, 300 );        ctx.lineTo( 100, 100 );        // 逆时针的正方形        ctx.moveTo( 150, 150 );        ctx.lineTo( 150, 250 );        ctx.lineTo( 250, 250 );        ctx.lineTo( 250, 150 );        ctx.lineTo( 150, 150 );        ctx.fill();   // 描边填充绘图    </script>

闭合路径 closePath

closePath(): 当我们进行绘图的时候,可以通过closePath方法来将结束的点和开始的点进行闭合。
案例:

    <canvas width='800' height='600' id='cas' style='border: 1px solid blue;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        ctx.moveTo( 100, 100 );        ctx.lineTo( 300, 100 );        ctx.lineTo( 300, 300 );        ctx.closePath();    // 闭合        ctx.stroke();   // 描边绘图    </script>

lineWidth: 可以用来设置线条的粗细。 ctx.lineWidth = 3;

canvas 为了图形能比较美观的展示,会自动给图形取消锯齿的操作,在原有图形线条上延展加像素宽1px左右并虚化的操作。所以线宽多多少少会有些偏差。

同时注意:moveTo是以线条的中心作为起始点的。 那么用 lineTo 闭合起来就会有问题。

    <canvas width="600" height="400" id="cas" style='border:1px solid black;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        ctx.lineWidth = 20;        ctx.moveTo( 50, 100 );        ctx.lineTo( 150, 100 );        ctx.lineTo( 150, 200 );        ctx.lineTo( 50, 100 );        ctx.moveTo( 200, 100 );        ctx.lineTo( 300, 100 );        ctx.lineTo( 300, 200 );        ctx.closePath();        ctx.stroke();    </script>

所以 closePath 与 直接使用 lineTo 闭合是有区别的,尽量使用 closePath 闭合

Canvas 中绘图是有状态的 - 开启新路径

Canvas 绘图是含有状态的, 在需要改变颜色, 绘制方法, 改变一些属性…

当需要换颜色,换fill或者换stroke等,就需要改变绘图状态, 使用 beginPath() 方法. 开启一个新的路径.

    <canvas width="600" height="400" id="cas" style='border:1px solid black;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        ctx.moveTo( 50, 100 );        ctx.lineTo( 150, 100 );        ctx.lineTo( 150, 200 );        ctx.closePath();        ctx.stroke();        ctx.beginPath();    // 下面的就不会影响到上面的了        ctx.moveTo( 200, 100 );        ctx.lineTo( 300, 100 );        ctx.lineTo( 300, 200 );        ctx.closePath();        ctx.fill();    </script>

设置线末端类型 lineCap - 线帽

设置线型末端的样式, 可取值为: ‘butt’( 默认 ), ‘round’, ‘square’. 默认方形

‘butt’ 表示两端使用方形结束. ctx.lineCap = ‘butt’;

‘round’ 表示两端使用圆角结束. ctx.lineCap = ‘round’;

‘square’ 表示突出的圆角结束. ctx.lineCap = ‘square’;

设置相交线的拐点 lineJoin - 线拐

设置两条直线的拐点描述方式. 可以取值 ‘round’, ‘bevel’, ‘miter’(默认)

‘round’ 使用圆角连接. ctx.lineJoin = ‘round’;

‘bevel’ 使用平切连接. ctx.lineJoin = ‘bevel’;

‘miter’ 使用直角转. ctx.lineJoin = ‘miter’;

    <canvas width="600" height="400" id="cas" style='border:1px solid black;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        ctx.moveTo( 50, 100 );        ctx.lineTo( 150, 100 );        ctx.lineTo( 150, 200 );        ctx.lineWidth = 20;        ctx.lineJoin = 'round'; // 线拐 圆角        ctx.closePath();        ctx.stroke();        ctx.beginPath();    // 下面的不会影响到上面的了        ctx.moveTo( 200, 100 );        ctx.lineTo( 200, 300 );        ctx.lineWidth = 20;        ctx.lineCap =  'round'; // 线帽 圆角        ctx.stroke();    </script>

虚线绘制

ctx.setLineDash( 数组 )   画虚线ctx.getLineDash()  获取设置的 数组ctx.lineDashOffset = 值  虚线偏移 + 右 - 左

ctx.setLineDash( 数组 ),数组中存储的数字就是分别表示 实线部分与空白部分的长度

    <canvas width="600" height="400" id="cas" style='border:1px solid black;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        ctx.setLineDash( [ 15, 5 ] ); // 实线 15 空白 5 为一个周期        // [ 15, 5, 20 ]奇数项时自动补全成 [ 15, 5, 20, 15, 5, 20 ]        // console.log( ctx.getLineDash() ); 可以看到就是 [ 15, 5, 20, 15, 5, 20 ]        // (实 15,空 5,实 20,空 15, 实 5,空 20) 为一个周期        ctx.moveTo( 100, 150 );        ctx.lineTo( 300, 150 );        ctx.stroke();    </script>

如何设置描边与填充的颜色

ctx.strokeStyle 设置描边的颜色
ctx.strokeStyle = ‘rgb( 255, 0, 0 )’ ; // 绘制 stroke 颜色

ctx.fillStyle 设置填充的颜色
ctx.fillStyle = ‘rgb( 255, 0, 0 )’ ; // 绘制 fill 颜色

注意每次换颜色都要 beginPath();

设置颜色案例:

    <canvas width="600" height="400" id="cas" style='border:1px solid black;'></canvas>    <script>        var cas = document.getElementById( 'cas' );        var ctx = cas.getContext( '2d' );        for ( var i = 0; i < 256; i++ ) {            ctx.beginPath();            ctx.strokeStyle = 'rgb( ' + i + ', ' + ( 255 - i ) + ', ' + i + ')';            ctx.moveTo( 50 + i, 100 );            ctx.lineTo( 50 + i, 300 );            ctx.stroke();        }    </script>

直线构造函数的 初步简陋封装

    <canvas width='600' height='400' id='cas' style='border: 1px solid blue;'></canvas>    <script>        var cas = document.getElementById('cas');        var ctx = cas.getContext('2d');        function Line( ctx, x0, y0, x1, y1 ) {            this.ctx = ctx;            this.x0 = x0;            this.y0 = y0;            this.x1 = x1;            this.y1 = y1;        }        Line.prototype = {            constructor : Line,            stroke : function() {                this.ctx.moveTo( this.x0, this.y0 );                this.ctx.lineTo( this.x1, this.y1 );                this.ctx.stroke();            }        }        var line = new Line( ctx, 100, 100, 400, 400 );        line.stroke();    </script>

目前的封装呢,不太完善,因为如果要进行设置绘制颜色啊,线帽啊等等时,就会参数十分庞大, 我们需要改良。

直线构造函数的 简陋改良版

    <canvas width='600' height='400' id='cas' style='border: 1px solid blue;'></canvas>    <script>        var cas = document.getElementById('cas');        var ctx = cas.getContext('2d');        function Line( config ) {            this.ctx = config.ctx;            this.points = config.points;            this.strokeStyle = config.strokeStyle;            this.lineWidth = config.lineWidth;        }        Line.prototype = {            constructor : Line,            stroke : function() {                this.ctx.moveTo( this.points[0], this.points[1] );                this.ctx.lineTo( this.points[2], this.points[3] );                if ( this.strokeStyle ) this.ctx.strokeStyle = this.strokeStyle;                if ( this.lineWidth ) this.ctx.lineWidth = this.lineWidth;                this.ctx.stroke();            }        }        var line = new Line( {            ctx: ctx,            points : [ 100, 100, 400, 100 ],            strokeStyle:'red',            lineWidth: 5        });        line.stroke();    </script>
1 0
原创粉丝点击