欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

纯HTML5 Canvas实现的饼图,,基本思路: 主要是利用H

来源: javaer 分享于  点击 11021 次 点评:254

纯HTML5 Canvas实现的饼图,,基本思路: 主要是利用H


基本思路:

主要是利用HTML5 Canvas实现饼图绘制,绘制弧度的API主要是使用

context.arc与lineto两个API。

实现的功能有:

支持标签Legend显示或者隐藏

首次载入动画效果

鼠标tooltip效果

自定义饼图大小与是否添加文字

效果如下:

调用代码:

<html><head><meta http-equiv="X-UA-Compatible" content="chrome=IE8"><script src="js/fishcomponent.js"></script><script src="js/pie.js"></script><title>My Demo 1</title>    <script>    window.onload = function() {        var canvas = document.getElementById("pie_canvas");        var seriesData = [{name:"apples", value:150, color:"RGBA(255,0,0,1)"},                      {name:"orange", value:100, color:"RGBA(255,255,0,1)"},                      {name:"banana", value:80, color:"RGBA(255,0,255,1)"},                      {name:"peaches", value:60, color:"RGBA(0,255,255,1)"},                      {name:"strawberries", value:40, color:"RGBA(0,127,255,1)"}]        var config = {                width : 600,                 height: 400,                series: seriesData,                canvas: canvas,                unit: "kg",                title:"Fruit Sales",                tooltips : {                    enable : true                },                animation :{                    enable: true                },                legend : {                    enable : true                },                text : {                    enable: true                },        };        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><div id="btn-group">    <button type="button" id="clear-button">Clear Plot</button>    <button type="button" id="refresh-button">Draw Plot</button></div></body></html>

饼图JS的代码:

```javascriptvar pieChart = { width: 600, height: 400, series: [], unit: "kg", chartCanvas: null, selectable : true, title: "Pie Chart", legend : { enable : true }, edge : { width: 50, height: 50 }, animation: { enable: true, animCanvas : null, hh: 1, // trick is here!! for animation play pctx: null }, tooltips: { enable: true, tooltipCanvas : null, ttContext: null, index: -1 }, circle : { cx: 0, cy: 0, radius: 0

},text : {    enable: false,    content:[]},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;    this.unit = config.unit;    if(config.tooltips != undefined) {        this.tooltips.enable = config.tooltips.enable;              }    if(config.animation != undefined) {        this.animation.enable = config.animation.enable;                }    if(config.legend != undefined) {        this.legend.enable = config.legend.enable;              }    if(config.text != undefined) {        this.text.enable = config.text.enable;    }},render : function() {    // initialization circle    this.circle.cx = this.width/2;    this.circle.cy = this.height/2;    this.circle.radius = Math.min(this.width/2, this.height/2) - Math.max(this.edge.width, this.edge.height);    var ctx = null;    if(this.animation.enable) {        this.animation.animCanvas = document.createElement("canvas");        this.animation.animCanvas.width = this.width;        this.animation.animCanvas.height = this.height;        ctx = this.animation.animCanvas.getContext("2d");    } else {        ctx = this.chartCanvas.getContext("2d");        this.renderBorder(ctx);    }    if(this.circle.radius <= 0) {        ctx.strokeText("Can not reader the chart, Circle is too small.");        return;    }    // draw each arc according to data series     var sum = 0;    var nums = this.series.length;    for(var i=0; i<nums; i++) {        sum += this.series[i].value;    }    // draw title    ctx.font = '18pt Calibri';    ctx.fillText(this.title, this.width/2 - this.edge.width, 30);    ctx.save();    var deltaArc = 0;    for(var i=0; i<nums; i++) {        var precent = this.series[i].value/sum;        this.renderPie(ctx, i, precent, deltaArc);        deltaArc += 2*Math.PI * precent;    }    ctx.restore();    // add blur shadow    ctx.save();    ctx.shadowColor = "black";    ctx.shadowOffsetX = 0;    ctx.shadowOffsetY = 0;    ctx.shadowBlur = 10;    ctx.beginPath();    ctx.arc(this.circle.cx, this.circle.cy, this.circle.radius, 0, Math.PI * 2, false);    ctx.closePath();    ctx.lineWidth = 1;    ctx.strokeStyle = "RGBA(127,127,127,1)";    ctx.stroke();    ctx.restore();    // render legend    ctx.save();    this.renderLegend(ctx, sum);    ctx.restore();    // play animation    if(this.animation.enable) {        var parent = this;        this.animation.pctx = this.chartCanvas.getContext("2d");        this.renderBorder(this.animation.pctx);        setTimeout(function() {parent.playAnimation(parent);}, 1000/20);                    }},showTooltips : function(loc, ctx) {    if(!this.tooltips.enable) {        return;    }    var dx = loc.x - this.width/2;    var dy = loc.y - this.height/2;    var dis = Math.floor(Math.sqrt(dx * dx + dy * dy));    if(dis <= this.circle.radius) {        // draw tool tip text        var angle = Math.atan2(dy,dx);        if(angle <= 0) {            // if[-Math.PI, 0], make it[Math.PI, 2*Math.PI]            angle = angle + 2*Math.PI;        }        var sum = 0;        var nums = this.series.length;        for(var s=0; s<nums; s++) {            sum += this.series[s].value;        }        var deltaArc = 0;        var index = 0;        for(var i=0; i<nums; i++) {            var precent = this.series[i].value/sum;            deltaArc += 2*Math.PI * precent;            if(angle<=deltaArc) {                index = i;                break;            }        }        if(this.tooltips.tooltipCanvas == null) {            this.tooltips.tooltipCanvas = document.createElement("canvas");            this.tooltips.ttContext = this.tooltips.tooltipCanvas.getContext("2d");            this.tooltips.tooltipCanvas.width = 150;            this.tooltips.tooltipCanvas.height = 100;        }        // only draw once        // if(index == this.tooltips.index){        //  return;        // }        this.clearTooltips(ctx);        this.tooltips.index = index;        var m_context = this.tooltips.ttContext;        m_context.save();        m_context.clearRect(0, 0, this.tooltips.tooltipCanvas.width, this.tooltips.tooltipCanvas.height);        m_context.lineWidth = 2;        m_context.strokeStyle = this.series[index].color;        m_context.fillStyle="RGBA(255,255,255,0.7)";        // m_context.strokeRect(2, 2, this.tooltips.tooltipCanvas.width-4, this.tooltips.tooltipCanvas.height-4);        // m_context.fillRect(2,2,this.tooltips.tooltipCanvas.width-4, this.tooltips.tooltipCanvas.height-4);        m_context.roundRect(2,2,this.tooltips.tooltipCanvas.width-4, this.tooltips.tooltipCanvas.height-4, 5, true, true);        m_context.font="14px Arial";        m_context.fillStyle="RGBA(0,0,0,1)";        m_context.fillText("Index: " + (index + 1), 5, 20);        m_context.fillText(this.series[index].name + ": " + this.series[index].value + this.unit, 5, 40);        m_context.fillText(this.series[index].precent, 5, 60);        m_context.restore();        // make tool-tip rectangle is always visible         if((loc.x + this.tooltips.tooltipCanvas.width)> this.width) {            loc.x = loc.x - this.tooltips.tooltipCanvas.width;        }        if((loc.y - this.tooltips.tooltipCanvas.height) <= 0) {            loc.y = loc.y + this.tooltips.tooltipCanvas.height;        }        ctx.drawImage(this.tooltips.tooltipCanvas, 0, 0, this.tooltips.tooltipCanvas.width, this.tooltips.tooltipCanvas.height,                 loc.x, loc.y-this.tooltips.tooltipCanvas.height, this.tooltips.tooltipCanvas.width, this.tooltips.tooltipCanvas.height);        } else {        this.tooltips.index = -1;        this.clearTooltips(ctx);    }},clearTooltips : function(ctx) {    ctx.clearRect(0,0,this.width, this.height);    this.renderBorder(ctx);    ctx.drawImage(this.animation.animCanvas, 0, 0, this.width, this.height, 0, 0, this.width, this.height); },renderBorder : function(ctx) {    ctx.save();    ctx.fillStyle="white";    ctx.strokeStyle="black";    ctx.fillRect(0, 0, this.width, this.height);    ctx.strokeRect(0, 0, this.width, this.height);    ctx.restore();},renderPie : function(ctx, index, precent, deltaArc) {    var endAngle = deltaArc + 2*Math.PI*precent;    ctx.beginPath();    ctx.arc(this.circle.cx, this.circle.cy, this.circle.radius, deltaArc, endAngle, false);    ctx.moveTo(this.circle.cx, this.circle.cy);    ctx.lineTo(this.circle.cx + this.circle.radius * Math.cos(deltaArc), this.circle.cy + this.circle.radius * Math.sin(deltaArc));    ctx.lineTo(this.circle.cx + this.circle.radius * Math.cos(endAngle), this.circle.cy + this.circle.radius * Math.sin(endAngle));    ctx.lineTo(this.circle.cx, this.circle.cy);    ctx.closePath();    ctx.fillStyle = this.series[index].color;    ctx.fill();    // render text content    if(this.text.enable) {                  var halfEndAngle = deltaArc + Math.PI*precent;        var hx = this.circle.cx + this.circle.radius * Math.cos(halfEndAngle);        var hy = this.circle.cy + this.circle.radius * Math.sin(halfEndAngle);        ctx.beginPath();        ctx.moveTo(hx, hy);        var linePos = (hx < this.circle.cx) ? (hx - this.edge.width) : (hx + this.edge.width);        ctx.lineTo(linePos, hy);        ctx.closePath();        ctx.strokeStyle="black";        ctx.stroke();        var textPos = (hx < this.circle.cx) ? (hx - this.edge.width*2) : (hx + this.edge.width);        precent = Math.round (precent*100) / 100;        var size = this.text.content.length;        var tipStr = (size > index) ? this.text.content[index] : this.series[index].name + ": " + (precent * 100).toFixed(0) + "%";        ctx.font = '10pt Calibri';        ctx.fillStyle="black";        ctx.fillText(tipStr, textPos, hy);    }},renderLegend : function(ctx, sum) {    if(!this.legend.enable) return;    var nums = this.series.length;    ctx.font = '10pt Calibri';    var pos = (this.width/2 > (this.circle.radius+50)) ? 50 : (this.circle.cx - this.circle.radius);    for(var i=0; i<nums; i++) {        var x = this.series[i].value/sum;        x = Math.round (x*100) / 100;        var tipStr =  this.series[i].name + ": " + (x * 100).toFixed(0) + "%";        this.series[i].precent = tipStr;        ctx.fillStyle = this.series[i].color;        ctx.fillRect(pos - 40, 20*i+10, 10, 10);        ctx.fillStyle = "black";        ctx.fillText(tipStr, pos - 25, 20*i+20);    }       },playAnimation : function(parent) {      if(parent.animation.hh < parent.height) {        parent.animation.pctx.save();        parent.animation.pctx.globalAlpha=0.5;        parent.animation.pctx.clearRect(0,0,parent.width, parent.height);        parent.renderBorder(parent.animation.pctx);        parent.animation.pctx.drawImage(parent.animation.animCanvas, 0, 0, parent.width, this.animation.hh, 0, 0, parent.width, this.animation.hh);        parent.animation.hh = parent.animation.hh + 10;        parent.animation.pctx.restore();                            setTimeout(function() {parent.playAnimation(parent);}, 1000/20);     } else {        parent.animation.pctx.clearRect(0,0,parent.width, parent.height);        parent.renderBorder(parent.animation.pctx);        parent.animation.pctx.drawImage(parent.animation.animCanvas, 0, 0, parent.width, parent.height, 0, 0, parent.width, parent.height);        // enable tool-tip functionality        if(parent.animation.enable &amp;&amp; parent.legend.enable) {            parent.chartCanvas.addEventListener('mousemove', function(event) {                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)};                parent.showTooltips(loc, (parent.animation.enable ? parent.animation.pctx : ctx));            }, false);        }    }},

};```源代码可以直接使用

相关栏目:

用户点评