h5 canvas手工写一个初级的饼状图,只为研究原理,自娱自乐

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<canvas id="pie" width="800px" height="600px" style="border: 1px solid #999999;margin: 0px;padding: 0;">
    (Your browser doesn't support canvas)
</canvas>
<script type="text/javascript">

    DomUtils = {
        addEventListener:function(obj,type,fn,context){
            function handler(e){
                return fn.call(context||obj,e);
            }
            if(obj.addEventListener){
                obj.addEventListener(type,handler,false);
            }
            else if(obj.attachEvent){
                obj.attachEvent("on"+type,handler);
            }
        },
        removeEventListener:function(){
            if(obj.addEventListener){
                obj.removeEventListener(type,fn,false);
            }
            else if(obj.attachEvent){
                obj.detachEvent("on"+type,handler);
            }
        }
    }

    var PieChart = function(){
        // func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])
        this.init.apply(this,arguments);
    };
    PieChart.prototype = {
        init:function(id,options){
            this.renderId = id;
            this.canvas = document.getElementById(this.renderId);
            this.data = options.data;
            this.colors = options.colors;
            this.labels = options.labels;
            this.linecolor = options.linecolor||"rgba(229, 205, 205, 0.58)";
            this.isCircle = options.isCircle;
            this.radius = options.radius||[];
            this.angles = [];
            this.prompt = null;
            this.center = {x:0,y:0,radius:50};
            this.offset = options.offset||100;
            this.legend = {
                width:20,
                height:10
            };
            this._calcAngle();
        },
        _calcAngle(){
            var startAngle = 0;
            var endAngle = 0;
            for(var i=0;i<this.data.length;i++){
                endAngle = startAngle+Number(this.data[i])*Math.PI*2;
                this.angles.push({
                    index:i,
                    label:this.labels[i],
                    color:this.colors[i],
                    start:startAngle,
                    end:endAngle
                });
                startAngle = endAngle;
            }
        },
        _draw:function(){
            // 开始绘画
            var width = this.canvas.width;
            var height = this.canvas.height;
            var radius = Math.min(width,height)/2-this.offset;
            var x = radius+this.offset;
            var y = height/2+this.canvas.offsetTop-8;
            this.center.x = x;
            this.center.y = y;
            this.center.radius = radius;
            var ctx = this.canvas.getContext("2d");
            this._antialiasing(ctx,width,height);
            ctx.strokeStyle = this.linecolor;
            for(var i=0;i<this.angles.length;i++){
                ctx.beginPath();
                ctx.moveTo(x,y);
                ctx.fillStyle=this.angles[i].color;
                ctx.arc(x,y,radius,this.angles[i].start,this.angles[i].end);
                ctx.closePath();
                ctx.lineWidth=1;
                //ctx.strokeStyle="#ffffff";
                ctx.fill();
                ctx.stroke();
            }
            this._drawCircle(ctx);
        },
        _antialiasing:function(ctx,width,height){
            if (window.devicePixelRatio) {
                this.canvas.style.width = width + "px";
                this.canvas.style.height = height + "px";
                this.canvas.height = height * window.devicePixelRatio;
                this.canvas.width = width * window.devicePixelRatio;
                ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
            }
        },
        _drawCircle:function(ctx){
            if(this.isCircle){
                ctx.beginPath();
                ctx.moveTo(this.center.x,this.center.y);
                ctx.fillStyle="#ffffff";
                ctx.arc(this.center.x,this.center.y,this.center.radius/3,0,Math.PI*2);
                ctx.closePath();
                ctx.fill();
            }
        },
        _drawLegend:function(){
            var ctx = this.canvas.getContext("2d");
            var x = this.canvas.offsetWidth-150;
            var y = this.offset;
            for(var i=0;i<this.angles.length;i++){
                ctx.beginPath();
                ctx.moveTo(x,y);
                ctx.fillStyle=this.angles[i].color;
                ctx.fillRect(x,y,this.legend.width,this.legend.height);
                // 绘制文字
                ctx.moveTo(x+this.legend.width+5, y+this.offset/2);
                ctx.font = 'bold 12px 微软雅黑';
                ctx.fillStyle = color_arr[i];
                ctx.fillText(this.angles[i].label,x+this.legend.width+5,y+this.offset/2)
                //ctx.closePath();
                //ctx.strokeStyle="#ffffff";
                ctx.fill();
                y = y + 20;
            }
        },
        _drawPrompt(x,y,index){
            var pie = this.angles[index];
            var d = this.data[index];
            if(!this.prompt){
                this.prompt = document.createElement("div");
                document.body.appendChild(this.prompt);
            }
            this.prompt.style.display = "block";
            this.prompt.style.background = "rgba(50, 50, 50, 0.701961)";
            this.prompt.style.position = "absolute";
            this.prompt.style.padding = "5px";
            this.prompt.style.zindex = "99999";
            this.prompt.style.color = "#fff";
            this.prompt.style.borderRadius = "4px";
            this.prompt.style.top = y+20+"px";
            this.prompt.style.left = x+20+"px";
            this.prompt.innerHTML = pie.label+"<br/>"+d;
        },
        _getPieIndex:function(x,y){
            var angle = Math.atan2(y,x);
            if (angle < 0) angle = -angle;
            else {
                angle = Math.PI * 2 - angle;
            }
            for(var i=0;i<this.angles.length;i++){
                if(angle<=this.angles[i].end){
                    return i;
                }
            }
        },
        _onMouseOver:function(){
            this._draw();
            var e = arguments.callee.caller.arguments[0]||event;
            var x = e.x|| e.clientX;
            var y = e.y|| e.clientY;
            var dx = x-this.center.x;
            var dy = this.center.y-y;
            var d = Math.sqrt(dx*dx+dy*dy);
            if(this.center.radius>=d){
                console.info(x+","+y);
                var index = this._getPieIndex(dx,dy);
                var ctx = this.canvas.getContext("2d");
                ctx.beginPath();
                ctx.moveTo(this.center.x,this.center.y);
                ctx.fillStyle=this.angles[index].color;
                ctx.lineWidth=1;
                ctx.arc(this.center.x,this.center.y,this.center.radius+20,this.angles[index].start,this.angles[index].end);
                ctx.closePath();
                ctx.fill();
                this._drawCircle(ctx);
                this._drawPrompt(x,y,index);
            }else{
                if(this.prompt)this.prompt.style.display="none";
            }
        },
        _dispatchEvent:function(){
            DomUtils.addEventListener(this.canvas,'mouseover',this._onMouseOver,this);
            //DomUtils.addEventListener(this.canvas,'mouseout',canvasOnMouseOut,this);
            DomUtils.addEventListener(this.canvas,'mousemove',this._onMouseOver,this);
        },
        render:function(){
            this._draw();
            this._dispatchEvent();
            this._drawLegend();
        }
    };

    var data_arr = [0.05, 0.25, 0.6, 0.1];
    var color_arr = ["#00FF21", "#FFAA00", "#00AABB", "#0044ff"];
    var text_arr = ["河北", "山东", "河南", "山西"];

    var piechart = new PieChart("pie",{
        isCircle:true,
        data:data_arr,
        colors:color_arr,
        labels:text_arr
    });
    piechart.render();

</script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值