Canvas 製作數據餅圖

html代碼
```<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    <style type="text/css">
        canvas{
            border: 1px solid salmon;
        }
    </style>

    </head>
    <body>
        <canvas id="cvs" width="500" height="500"></canvas>
        <script src="../js/pipe_new.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">

            var cvs= document.getElementById("cvs");
            var ctx = cvs.getContext("2d");
             var pipe = new Pipe( 200, 200, 80, [
            {
                val: 10,
                msg: '米飯'
            },
            {
                val: 30,
                msg: '麪條'
            },
            {
                val: 50,
                msg: '饅頭'
            },
            {
                val: 50,
                msg: '豆腐腦'
            },
            {
                val: 50,
                msg: '餃子'
            },
            {
                val: 90,
                msg: '湯圓'
            },
        ] );
        pipe.draw();


        </script>


    </body>
</html>





<div class="se-preview-section-delimiter"></div>

這裏寫代碼片
“`

js代碼


    // 把角度轉換爲弧度
    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();

                // 繪製文字
                if ( lineAngle >= 90 && lineAngle <= 270 ) {
                    ctx.textAlign = 'right';

                }else {
                    ctx.textAlign = 'left';

                }
                ctx.font="16px 宋體";
                ctx.fillText( obj.msg, lineX, lineY );

            });
        }
    } )


運行效果圖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章