JS 饼图/环形图表

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiaofengma/article/details/76256991

js 圆形/环形图表

最近公司项目要求开发环形图表客户端(Android/IOS)组件,一开始想使用原生实现,但是需要开发2套代码,最后决定使用js来实现图表,原生调用html代码展示。


效果如下:
这里写图片描述
直接上代码:


html代码:

<html>  
<head>   
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> 
<script src="pieChart.js"></script>  
<title>My Demo 1</title>  
    <script>  
    window.onload = function() {  
        var canvas = document.getElementById("pie_canvas");  
        var seriesData = [{name:"apples", value:0.1, color:"#FF00aa",label1:"描述1",label2:"200元"},  
                      {name:"orange", value:0.2, color:"#FF0011",label1:"描述2",label2:"200元"},  
                      {name:"banana", value:0.3, color:"#FFaaFF",label1:"描述3",label2:"200元"},  
                      {name:"peaches", value:0.2, color:"#FF33FF",label1:"描述4",label2:"200元"},  
                      {name:"strawberries", value:0.2, color:"#FF99FF",label1:"描述5",label2:"200元"}]  
        var config = {  
                width : 400,   
                height: 400,  
                series: seriesData,  
                canvas: canvas,   
                title:"Fruit Sales",
                callback:function(obj){
                    console.log(obj.label1);
                }
        };  
        pieChart.initSettings(config);  
        pieChart.render();  

    }  
    </script>  
</head>  
<body>  
<h1>Pie Chart Demo</h1>  
<div id="my_container" style="width:600px; height:500px;">  
    <canvas id="pie_canvas"></canvas>  
</div>   
</body>  
</html>  

JS代码块:

var pieChart = {  
    title: "Pie Chart", 
    width: 400,  
    height: 400,  
    series: [],  //格式[{"name":"","value":"","color":"","label1":"","label2":""}]
    chartCanvas: null, 
    callback:null ,
    legend : {  
        show : true  
    }, 
    label:{
        show:true,
        linelength:40,
        linelength2:50
    },
    circle : {  
        cx: 0,  
        cy: 0,  
        radius: 0  

    }, 
    initSettings: function (config) {  
        this.chartCanvas = config.canvas;  
        this.chartCanvas.width = config.width;  
        this.chartCanvas.height = config.height;  
        this.width = config.width;  
        this.height = config.height;  
        this.series = config.series;  
        this.title = config.title;    
        if(config.legend != undefined) {  
            this.legend.show = config.legend.show;            
        }
        if(config.label != undefined) {  
            this.label.show = config.label.show;            
        }
        this.callback = config.callback;
    },
    getRatioSum:function(j){
        var sum = 0;
        for (var i = 0; i < j; i++) {
            sum += this.series[i].value;
        }
        return sum;
    },
    getRatioHalfSumDegrees:function(index){
        var sum = this.getRatioSum(index);
        sum += (this.series[index].value / 2);
        return sum * Math.PI * 2;
    },
    getRatioHalfSumDegrees360:function(index){
        var sum = this.getRatioSum(index);
        sum += (this.series[index].value / 2);
        return sum * 360;
    },
    renderLegend:function(ctx, length){
    },
    renderLabel:function(ctx,length){
        if(this.label.show){
            for (var i = 0; i <length; i++) {
                this.renderLabelLine(ctx,i) ;
            }

        }
    },
    renderLabelLine:function(ctx,index){
        ctx.save();
        ctx.translate(this.width / 2, this.height / 2);
        ctx.rotate(this.getRatioHalfSumDegrees(index));
        ctx.strokeStyle = this.series[index].color;
        ctx.moveTo(this.circle.radius + 1, 0);
        ctx.lineTo(this.circle.radius + this.label.linelength, 0);
        ctx.stroke();
        this.renderLabelLine2(ctx, index);
        ctx.restore();
    },
    renderLabelLine2:function(ctx,index){
        ctx.save();
        ctx.translate(this.circle.radius + this.label.linelength, 0);
        var ro = this.getRatioHalfSumDegrees(index);
        ctx.rotate( - ro);
        var xro = this.getRatioHalfSumDegrees360(index);
        if ((xro > 270 && xro < 360) || (xro > 0 && xro < 90)) {
            ctx.strokeStyle = this.series[index].color;
            ctx.moveTo(0, 0);
            ctx.lineTo(this.label.linelength2, 0);
            ctx.stroke();
            ctx.fillText(this.series[index].label1, 10, -4);
            ctx.fillText(this.series[index].label2, 10, 14); 
        } else {
            ctx.strokeStyle = this.series[index].color;
            ctx.moveTo(0, 0);
            ctx.lineTo( - this.label.linelength2, 0);
            ctx.stroke();
            ctx.fillText(this.series[index].label1, -40, -4);
            ctx.fillText(this.series[index].label2, -40, 14); 
        }

        ctx.restore();
    },
    renderPie:function(ctx,length){
        let lastpos = pos = 0;
        ctx.lineWidth = this.circle.radius * 0.4;
        for (let i = 0; i < length; i++) {
            ctx.beginPath();
            ctx.strokeStyle = this.series[i].color;
            pos = lastpos + Math.PI * 2 * this.series[i].value;
            ctx.arc(this.circle.cx , this.circle.cy, this.circle.radius, lastpos, pos);
            ctx.stroke();
            lastpos = pos;
        }

    },
    renderPieImage:function(ctx,length){

    },
    renderClick:function(event,obj){
        var x = event.pageX;
        var y = event.pageY;
        var canvas = event.target;
        var bbox = canvas.getBoundingClientRect();
        var loc = { x: x - bbox.left * (canvas.width  / bbox.width),
                    y: y - bbox.top  * (canvas.height / bbox.height)};
        console.log(loc);

        var dx = loc.x - obj.circle.cx;  
        var dy = loc.y - obj.circle.cy;  
        var dis = Math.floor(Math.sqrt(dx * dx + dy * dy));  
        console.log("dis="+dis+"  mRadius="+obj.circle.radius);
        if(dis <= obj.circle.radius*1.2&&dis>=obj.circle.radius*0.8) {  
            // draw tool tip text  
            var angle = Math.atan2(dy,dx);  
            if(angle <= 0) {   
                angle = angle + 2*Math.PI;  
            }   
            var deltaArc = 0;  
            var index = 0;  
            for(var i=0; i<obj.series.length; i++) {  
                var precent = obj.series[i].value;  
                deltaArc += 2*Math.PI * precent;  
                if(angle<=deltaArc) {  
                    index = i;  
                    break;  
                }  
            }
            obj.callback(obj.series[index]);
            //console.log(obj.series[index].label1);
        }
    },
    render:function(){
        this.circle.cx = this.width/2 ;
        this.circle.cy = this.height/2 ;
        this.circle.radius=(this.width - this.width  * 0.5) / 2;
        var ctx = this.chartCanvas.getContext("2d");
        if(this.circle.radius <= 0) {  
            ctx.strokeText("请设置布局大小.");  
            return;  
        }   
         if (window.devicePixelRatio) {
            this.chartCanvas.style.width = this.width + "px";
            this.chartCanvas.style.height = this.height + "px";
            this.chartCanvas.height = this.height * window.devicePixelRatio;
            this.chartCanvas.width = this.width * window.devicePixelRatio;
            ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
        }
        var length = this.series.length ;
        this.renderLabel(ctx,length) ;
        this.renderPie(ctx,length); 
        var parent = this ;
        this.chartCanvas.addEventListener('click', function(event){
            parent.renderClick(event,parent);
        }, false);
    }

}

猜你喜欢

转载自blog.csdn.net/qiaofengma/article/details/76256991