Canvas知识点之一

1.canvas标签的简单使用


<body>
    <!-- canvas是一个用来展示绘图效果的标签,它和img类似,都是行内块元素 -->
    <!-- 同一个页面可以拥有多个canvas标签 -->
    <!-- 画布默认300*150,要设置画布的宽高,需要借助canvas元素的属性 -->
    <canvas id="cvs" width="600" height="600"></canvas>
    <script>
    var cvs = document.getElementById('cvs');

    /*
     * 上面的canvas只是用来展示绘图效果的,
     * 那么这个图从哪里来的呢?
     * 需要打开canvas(通过getContext方法来打开),然后在上面绘图图形,
     * 最终就可以透过canvas标签看到。
     * */
    var ctx = cvs.getContext('2d');

    /*
     * canvas绘图的几个步骤:
     * 1、先移动钢笔到指定的位置
     * 2、开始画线条
     * 3、描边路径
     * */

    // 1、先移动钢笔到指定的位置
    // ctx.moveTo( x轴移动的坐标,y轴移动的坐标 )
    ctx.moveTo(10, 10);

    // 2、开始画线条
    // ctx.lineTo( x轴移动的坐标,y轴移动的坐标 )
    ctx.lineTo(110, 10);
    ctx.lineTo(110, 110);
    ctx.lineTo(10, 110);
    // 下面这句等价于ctx.closePath();
    ctx.lineTo(10, 10);

    // 颜色设置,必须放在绘制之前
    ctx.strokeStyle = 'blue';
    // 线宽设置,必须放在绘制之前
    ctx.lineWidth = 2;

    // 3、描边路径
    ctx.stroke();
    </script>
</body>

显示效果:为一个蓝色矩形

2.
// 放了防止重绘之前的路径,所以先把之前的路径清除掉
this.ctx.beginPath();

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <canvas id="cvs"></canvas>
    <script>
        var cvs = document.getElementById('cvs');
        var ctx = cvs.getContext('2d');

        // 构造函数
        function MyRect( ctx, startX, startY, width, height, lineWidth, strokeStyle ) {
            this.ctx = ctx;
            this.startX = startX;
            this.startY = startY;
            this.width = width;
            this.height = height;
            this.lineWidth = lineWidth;
            this.strokeStyle = strokeStyle;
        }

        // 给原型添加一个绘制方法
        MyRect.prototype.draw = function() {
            **// 放了防止重绘之前的路径,所以先把之前的路径清除掉
            this.ctx.beginPath();**

            this.ctx.moveTo( this.startX, this.startY );
            this.ctx.lineTo( this.startX + this.width, this.startY );
            this.ctx.lineTo( this.startX + this.width, this.startY + this.height );
            this.ctx.lineTo( this.startX, this.startY + this.height );
            this.ctx.closePath();

            this.ctx.lineWidth = this.lineWidth;
            this.ctx.strokeStyle = this.strokeStyle;

            this.ctx.stroke();
        }

        var myRect = new MyRect( ctx, 10, 10, 60, 60, 4, 'deeppink' );
        myRect.draw();

        var myRect2 = new MyRect( ctx, 100, 10, 100, 100, 6, 'skyblue' );
        myRect2.draw();
    </script>
</body>
</html>

3.非零环绕原则
这个原理其实很简单,发一个链接,大家去看下,Canvas中的非零环绕规则原理
先看这个链接的最后一个例子,画同心圆的时候,用的方法context.arc
的语法:
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
参数 描述
x 圆的中心的 x 坐标。
y 圆的中心的 y 坐标。
r 圆的半径。
sAngle 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle 结束角,以弧度计。
counterclockwise 可选。规定应该逆时针还是顺时针绘图。
False = 顺时针,true = 逆时针。
这个例子中,outer圆是true逆时针画的,inner圆是false顺时针画的,先在圆的边框上画出对应的箭头,
那么,我们根据非零环绕原则:
这里写图片描述
在从1区域画的线,与其相交的两个曲线,一个顺时针,一个逆时针,结果为0,所以1区域不会被fill(填充)。
再看2区域,只有一条曲线与其相交,逆时针的线,结果为-1,所以2区域会被填充,就是这么easy了。如果画举行,你是怎么样一步一步lineTo,lineTo的就决定了画法的方向。

尝试下画一个中空的矩形吧:

<body>
    <canvas id="cvs"></canvas>
    <script>
    var cvs = document.getElementById('cvs');
    var ctx = cvs.getContext('2d');

    // 封装一个绘制矩形的函数
    function MyRect(startX, startY, width, height, lineWidth, strokeStyle) {

        ctx.moveTo(startX, startY);
        ctx.lineTo(startX + width, startY);
        ctx.lineTo(startX + width, startY + height);
        ctx.lineTo(startX, startY + height);
        ctx.closePath();

        ctx.lineWidth = lineWidth;
        ctx.strokeStyle = strokeStyle;

        ctx.stroke();
    }

    // 顺时针画一个大矩形
    MyRect(10, 10, 100, 100, 6, 'skyblue');


    //这一句不需要了 ctx.beginPath(); 

    // 逆时针画一个小矩形
    ctx.moveTo(35, 35);
    ctx.lineTo(35, 55);
    ctx.lineTo(55, 55);
    ctx.lineTo(55, 35);
    ctx.closePath();

    ctx.lineWidth = 4;
    ctx.strokeStyle = 'blue';
    // 利用非0环绕原则原则
    ctx.fillStyle = 'yellow';
    // 一起填充
    ctx.fill();
    </script>
</body>

4.fill( ) 和 stroke( )方法的调用顺序问题

 在sublime中跑一下就看出区别了
    <script>
        var cvs = document.getElementById('cvs');
        var ctx = cvs.getContext('2d');

        // 封装一个绘制矩形的函数
        function juXing( startX, startY, width, height, lineWidth, strokeStyle, fillStyle ) {
            ctx.moveTo( startX, startY );
            ctx.lineTo( startX + width, startY );
            ctx.lineTo( startX + width, startY + height );
            ctx.lineTo( startX, startY + height );
            ctx.closePath();
            ctx.lineWidth = lineWidth;
            ctx.strokeStyle = strokeStyle;
            ctx.fillStyle = fillStyle;

            ctx.fill();
            ctx.stroke();
        }

        /*
        * 描边的时候,会占用原图形的一部分( 线宽的一半 )。
        * 所以,日常开发中,为了让线宽符合要求,
        * 最好先填充,再描边,防止填充时覆盖掉线宽的一半。
        * */
    </script>

5.线帽样式


<body>
    <canvas id="cvs" width="500" height="500"></canvas>
    <script>
        var cvs = document.getElementById('cvs');
        var ctx = cvs.getContext('2d');

        /*
        * 设置线帽样式:
        * ctx.lineCap = ‘butt' 、'round'、'square'
        * butt是默认值,
        * round线头是圆的,
        * square线头两段各增加线宽的一半。
        * */

        ctx.lineWidth = 10;

        // 默认线头
        ctx.moveTo( 10, 10 );
        ctx.lineTo( 310, 10 );
        ctx.stroke();

        // 增长线头,两端各增长线宽的一半
        ctx.beginPath();
        ctx.lineCap = 'square';
        ctx.moveTo( 10, 30 );
        ctx.lineTo( 310, 30 );
        ctx.stroke();

        // 圆线头,两端的圆半径为线宽的一半
        ctx.beginPath();
        ctx.lineCap = 'round';
        ctx.moveTo( 10, 50 );
        ctx.lineTo( 310, 50 );
        ctx.stroke();
    </script>
</body>

6.线交点样式


<body>
    <canvas id="cvs" width="500" height="500"></canvas>
    <script>
        var cvs = document.getElementById('cvs');
        var ctx = cvs.getContext('2d');

        /*
        * 设置线帽样式:
        * ctx.lineJoin = ‘miter' 、'round'、'bevel'
        * miter是默认值,两边向外延伸相交为尖尖角,
        * round是圆头,
        * bevel两边相连为一个斜面。
        * */

        ctx.lineWidth = 10;

        // 默认交点为尖尖角
        ctx.lineJoin = 'miter';
        ctx.moveTo( 10, 10 );
        ctx.lineTo( 60, 110 );
        ctx.lineTo( 110, 10 );
        ctx.stroke();

        // 交点为圆头
        ctx.beginPath();
        ctx.lineJoin = 'round';
        ctx.moveTo( 10, 50 );
        ctx.lineTo( 60, 150 );
        ctx.lineTo( 110, 50 );
        ctx.stroke();

        // 交点为斜面
        ctx.beginPath();
        ctx.lineJoin = 'bevel';
        ctx.moveTo( 10, 90 );
        ctx.lineTo( 60, 190 );
        ctx.lineTo( 110, 90 );
        ctx.stroke();
    </script>
</body>

7.用清除画布的方法让画布移动起来

<body>
    <canvas id="cvs" width="500" height="500">
    </canvas>
    <script>
    var cvs = document.getElementById('cvs');
    var ctx = cvs.getContext('2d');

    function Rect(ctx, originX, originY, width, height, linewidth, strokestyle) {
        this.ctx = ctx;
        this.originX = originX;
        this.originY = originY;
        this.width = width;
        this.height = height;
        this.linewidth = linewidth;
        this.strokestyle = strokestyle;
    }

    Rect.prototype.draw = function() {
        this.ctx.beginPath();
        this.ctx.moveTo(this.originX, this.originY);
        this.ctx.lineTo(this.originX + this.width, this.originY);
        this.ctx.lineTo(this.originX + this.width, this.originY + this.height);
        this.ctx.lineTo(this.originX, this.originY + this.height);
        this.ctx.closePath();

        this.ctx.lineWidth = this.linewidth;
        this.ctx.strokeStyle = this.strokestyle;
        this.ctx.stroke();
    }

    var rect = new Rect(ctx, 10, 10, 60, 60, 4, 'deeppink');
    rect.draw();

    setInterval(function() {
        // 把画布上的内容都清空
        ctx.clearRect(0, 0, cvs.width, cvs.height);
        rect.originX += 2;
        rect.draw();
    }, 0.5);
    </script>
</body>

8.绘制虚线ctx.setLineDash( )和ctx.lineDashOffset( )

知识点:
   <script>
        /*
        * 数组map方法,es5提供的
        * 语法: 数组.map( function( val, index, arr ) { return 1; } )
        * 返回值:把回调reurn的值共同组成一个数组
        * */

        var arr = [ 1, 2, 3, 4, 5];

        var newArr = arr.map( function( val, index ) {
            return val * 10;
        });
        console.log( newArr );
    </script>


----------


    <canvas id="cvs"></canvas>
    <script>
        var cvs = document.getElementById('cvs');
        var ctx = cvs.getContext('2d');
        /*
        * 设置画线的时候空白部分和实线部分的大小。
        * ctx.setLineDash( [ 5, 3 ] )
        * */
        ctx.lineDashOffset = 3;
        ctx.setLineDash( [ 4, 3, 2 ] );

        ctx.moveTo( 10, 10 );
        ctx.lineTo( 310, 10 );
        ctx.stroke();
        /*
         * 获取线条绘制规则。
         * ctx.getLineDash()
         * */
        console.log(ctx.getLineDash());

        /*
        * 设置虚线绘制时的偏移量
        * ctx.lineDashOffset = 3;
        * */
    </script>

9.画一个坐标轴,画出箭头,画几个点,并连线起来

<body>
    <canvas id="cvs" width="500" height="500"></canvas>
    <script>
        var cvs = document.getElementById('cvs');
        var ctx = cvs.getContext('2d');

        ctx.lineWidth = 2;

        // 坐标轴距离画布上右下左的边距
        var padding = {
            top: 20,
            right: 20,
            bottom: 20,
            left: 20
        }

        // 坐标轴中箭头的宽和高
        var arrow = {
            width: 12,
            height: 20
        }

        // 求坐标轴上顶点的坐标
        var vertexTop = {
            x: padding.left,
            y: padding.top
        }

        // 求坐标轴原点的坐标
        var origin = {
            x: padding.left,
            y: cvs.height - padding.bottom
        }

        // 求坐标轴右顶点的坐标
        var vertexRight = {
            x: cvs.width - padding.right,
            y: cvs.height - padding.bottom
        }


        // 画坐标轴中的两条线
        ctx.moveTo( vertexTop.x, vertexTop.y );
        ctx.lineTo( origin.x, origin.y );
        ctx.lineTo( vertexRight.x, vertexRight.y );
        ctx.stroke();

        // 画上顶点箭头
        ctx.beginPath();
        ctx.moveTo( vertexTop.x, vertexTop.y );
        ctx.lineTo( vertexTop.x - arrow.width / 2, vertexTop.y + arrow.height );
        ctx.lineTo( vertexTop.x, vertexTop.y + arrow.height / 2 );
        ctx.lineTo( vertexTop.x + arrow.width / 2, vertexTop.y + arrow.height );
        ctx.closePath();
        ctx.fill();

        // 画右顶点箭头
        ctx.beginPath();
        ctx.moveTo( vertexRight.x, vertexRight.y );
        ctx.lineTo( vertexRight.x - arrow.height, vertexRight.y - arrow.width / 2 );
        ctx.lineTo( vertexRight.x - arrow.height / 2, vertexRight.y );
        ctx.lineTo( vertexRight.x - arrow.height, vertexRight.y + arrow.width / 2 );
        ctx.closePath();
        ctx.fill();

        /*
        * 在坐标轴中指定位置画点,坐标算法:
        * 点的x轴:原点x坐标 + 点到原点的水平距离
        * 点的y轴:原点y坐标 - 点到原点的垂直距离
        * */

        // 需求,利用折线图的方式展示一下门口大爷酱香饼每日销售量
        // [ 10, 20, 50, 80, 120, 300, 100, 50, 2 ];

        var data = [ 10, 20, 50, 80, 120, 300, 100, 50, 2 ];

        // 画点
        data.forEach( function( val, index ) {
            console.log(val,index);
            ctx.fillRect( origin.x + index * 20 - 2, origin.y - val - 2, 4, 4 );
        });

        // 画折线
        ctx.beginPath();
        data.forEach( function( val, index ) {
            ctx.lineTo( origin.x + index * 20, origin.y - val );
        });
        ctx.stroke();
    </script>
</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值