Canvas知识点之二

1.补充一个数组的map方法:

        /*
        * map方法定义在Array.prototype上,所以所有的数组都可以访问
        * 语法:数组.map( 回调函数 )
        * 作用:接收回调函数的返回值,共同构成一个新数组返回。
        * */

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

        var newArr = arr.map( function( val, i, arr ) {
            return val * 5 - i;
        });

        console.log( newArr );

2.canvas是基于状态:

        /*
        * canvas是基于状态:
        * strokeStyle = 'red';
        * strokeStyle = 'blue';
        * 主要strokeStyle变化了,那么接下来所有和描边相关的绘制方法都会受到影响。
        * */
      例如:
          <canvas id="cvs" width="500" height="500"></canvas>
    <script>
    var cvs = document.getElementById('cvs');
    var ctx = cvs.getContext('2d');

    ctx.strokeStyle = 'blue';
    ctx.strokeRect(10,10,50,50);

    // ctx.strokeStyle = 'red'; 屏蔽这一句,两个矩形框颜色都是blue,打开后第二个变为red
    ctx.strokeRect(50,50,50,50);
    </script>

3.在画布上画好内容后,使用toDataURL方法可把画布内容转化为base64编码格式的图片,可以尝试使用打印的内容替换canvas标签看下效果

        // 把画布的内容转换为base64编码格式的图片
        console.log(cvs.toDataURL( 'image/png' ));

        /*·
        * base64编码图片的应用:
        * 如果一个网站中有少量的小图片,可以考虑直接使用base64编码。
        * */

4.画弧形
最主要是理解ctx.arc中起始角度和终止角度在哪里,是顺时针还是逆时针
这里写图片描述

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

        /*
        * 画弧( 画的是路径 )
        * ctx.arc( 圆心x轴坐标,圆心y轴坐标,半径, 起点弧度,结束点弧度,是否逆时针画(可选) )
        * arc方法内部会先从路径结束点到弧的起点画一条路径线。
        * 起点弧度、结束点弧度以及弧度的方向共同决定了弧的大小。
        * */

        // 把角度转换为弧度
        function angleToRadian( angle ) {
            return Math.PI / 180 * angle;
        }

        // 顺时针画一段弧 看清楚哪里是90度 哪里是270度 顺时针哦 别搞错了!!!
        ctx.arc( 100, 100, 30, angleToRadian( 90 ), angleToRadian( 270 ),false );
        ctx.stroke();

        // 逆时针画一段弧
        ctx.beginPath();
        ctx.arc( 200, 100, 30, angleToRadian( 90 ), angleToRadian( 270 ), true );
        ctx.stroke();

        // 一个圆
        ctx.beginPath();
        ctx.arc( 300, 100, 30, angleToRadian( 90 ), angleToRadian( 360 ) );
        ctx.stroke();

        /*
        * 画扇形:
        * 1、先设置路径起点为圆心
        * 2、画弧
        * 3、闭合路径
        * */
        ctx.beginPath();
        ctx.moveTo( 250, 250 ); //默认是顺时针
        ctx.arc( 250, 250, 90, angleToRadian( 45 ), angleToRadian( 180 ) );
        ctx.closePath();
        ctx.stroke();

    </script>

5.求一组数中的最大值,用call和apply的方法(为下面讲解做铺垫…)

    var numMax = Math.max(2,3,4,6,8,9);

    // 用call方法
    var num = Math.max.call(null,(2,3,4,6,8,9));

    // 用apply的方法
    var numArr = [2,3,4,6,8,9];
    var num = Math.max.apply(null,numArr);

    console.log(num);

6.在canvas上画空心字,实心字,以及各自的参考点

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

        /*
        * 设置文字的属性
        * ctx.font = 和css语法一样。
        * 注意:这里设置字体大小时必须带单位,单位支持css的所有表示方式。
        * 注意:单独设置字体大小不会生效,必须要加一个额外属性样式。
        * */

        ctx.font = '2rem 微软雅黑';
        /*
        * 绘制描边文字:
        * ctx.strokeText( 文字, 参考x轴坐标,参考y轴坐标,限制文字的最大长度(可选) )
        * */
        ctx.strokeText( '我是空心字体strokeText', 100, 100 );

        /*
         * 绘制填充文字:
         * ctx.fillText( 文字, 参考x轴坐标,参考y轴坐标,限制文字的最大长度(可选) )
         * */
        ctx.fillText( '我是实心字fillText', 100, 200 );


        // 绘制空心文字的参考点
        ctx.beginPath();
        ctx.arc( 100, 100, 4, 0, Math.PI * 2 );
        ctx.stroke();

        // 绘制实心文字的参考点
        ctx.beginPath();
        ctx.arc( 100, 200, 4, 0, Math.PI * 2 );
        ctx.fill();
    </script>

这里写图片描述

7.canvas上字的参考点和基线共同决定了字的位置

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

        ctx.font = '2rem 微软雅黑';

        /*
        * 设置文字的水平对其方式:
        * ctx.textAlign = 'left || start' 、 'right || end' 、 'center'
        * 默认值为start。
        * */

        /*
        * 设置文字的垂直对其方式:
        * ctx.textBaseline = 'top' 、'bottom'、'middle'、'alphabetic'、'hanging'、'ideographic'
        * 默认值为alphabetic。
        * */
       // 以参考点为坐标轴(0,0)画x,y轴,x轴即为基线
        //textAlign表示参考点在字的哪一侧(左中右)
        ctx.textAlign = 'left';

        //textBaseline表示基线在字的哪一侧(上中下)
        ctx.textBaseline = 'bottom';
        ctx.fillText( '位置取决于参考点和基线', 100, 200 );

        // 绘制文字的参考点
        ctx.beginPath();
        ctx.arc( 100, 200, 4, 0, Math.PI * 2 );
        ctx.fill();
    </script>

这里写图片描述

8.如何用正弦余弦函数来求圆上某一点的坐标?
我们在正常的坐标系中是向右为x正向,向上为y正方向,角度时逆时针转的。
在我们的画布上,角度时顺指针转的,向右是0度,是X轴正方向,垂直向下是90度,是Y轴正方法,所以公式依然适用。

假设圆心的坐标为(a,b),那么圆的方程是(x-a)^2+(y-b)^2=r^2
根据方程可以求出圆上的各点坐标,已知角度m,圆上点的坐标分别是:(r*cosm+a,r*sinm+b)

9.有了上面那么多铺垫,我们来画一个饼状图,形状如下:
这里写图片描述

pie_chart.js

(function( w ) {

    // 把角度转换为弧度
    function angleToRadian( angle ) {
        return Math.PI / 180 * angle;
    }

    // 混入式继承
    function extend( o1, o2 ) {
        for ( var key in o2 ) {
            // 只有o2自己的属性才会copy到o1身上
            if ( o2.hasOwnProperty( key ) ) {
                o1[ key ] = o2[ key ];
            }
        }
    }

    /*
     * constrcutor { Pipe } 饼图构造函数
     * param { x: number } 圆心x轴坐标
     * param { y: number } 圆心y轴坐标
     * param { r: number } 圆半径
     * param { data: Array } 绘制饼图所需的数据
     * */
    function Pipe( x, y, r, data ) {

        this.x = x;
        this.y = y;
        this.r = r;
        this.data = data;

        // 一组颜色
        this.colors = [ 'orange', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'peru', 'pink' ];
    }

    // 给原型扩充方法
    extend( Pipe.prototype, {

        // 绘制饼图
        draw: function() {

            // 在外面保存一下this
            var self = this;

            // 数据的总和
            var num = 0;
            this.data.forEach( function( obj ) {
                num += obj.val;
            });

            // 一个数据值所占用的角度
            var baseAngle = 360 / num;

            // 假设一开始就绘制了一个起始为0,结束为0的扇形
            var startAngle = 0,
                endAngle = 0,
                lineAngle = 0,
                lineX, lineY;

            // 画扇形
            this.data.forEach( function( obj, i ) {

                // 每次进来,计算当前扇形的起始角度和结束角度

                // 下一个扇形的起始角度,是当前扇形的结束角度
                startAngle = endAngle;
                // 这个结束角度 = 上一个扇形的结束角度 + 当前数值所对应的角度
                endAngle = endAngle + baseAngle * obj.val;

                // 求扇形中间线的角度
                lineAngle = startAngle + baseAngle * obj.val / 2;
                /*
                * 根据中间线的角度,求中间的线的x和y坐标:
                * x = 圆心x + r * Math.cos( angleToRadian( pointAngle ) )
                * y = 圆心y + r * Math.sin( angleToRadian( pointAngle ) )
                * */
                lineX = self.x + ( self.r + 20 ) * Math.cos( angleToRadian( lineAngle ) );
                lineY = self.y + ( self.r + 20 ) * Math.sin( angleToRadian( lineAngle ) );


                // 画每一个扇形
                ctx.beginPath();
                ctx.moveTo( self.x, self.y );
                ctx.arc( self.x, self.y, self.r, angleToRadian( startAngle ), angleToRadian( endAngle ) );
                ctx.closePath();
                ctx.fillStyle = self.colors[ i ];
                ctx.fill();

                // 画每一个扇形的平分线
                ctx.beginPath();
                ctx.moveTo( self.x, self.y );
                ctx.lineTo( lineX, lineY );
                ctx.strokeStyle = self.colors[ i ];
                ctx.stroke();

                // 绘制文字
                ctx.textBaseline = 'center';
                if ( lineAngle >= 90 && lineAngle <= 270 ) {
                    ctx.textAlign = 'right';
                }else {
                    ctx.textAlign = 'left';
                }
                ctx.fillText( obj.msg, lineX, lineY );
            });
        }
    } );

    // 把构造函数暴露到全局
    w.Pipe = Pipe;

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

        // [ 10, 30, 50, 60, 20 ]
        var pipe = new Pipe( 200, 200, 80, [
            {
                val: 10,
                msg: '手机震动'
            },
            {
                val: 30,
                msg: '有人在敲门'
            },
            {
                val: 50,
                msg: 'TA好像喜欢我'
            },
            {
                val: 50,
                msg: '忙完这事就轻松了'
            },
            {
                val: 50,
                msg: '这次考试还可以'
            },
            {
                val: 90,
                msg: '今晚早点睡觉'
            },
        ] );
        pipe.draw();
    </script>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值