纯HTML5 Canvas实现的饼图详解编程语言
2023-06-13 09:20:28 时间
基本思路:
主要是利用HTML5 Canvas实现饼图绘制,绘制弧度的API主要是使用
context.arc与lineto两个API。
实现的功能有:
1. 支持标签Legend显示或者隐藏
2. 首次载入动画效果
3. 鼠标tooltip效果
4. 自定义饼图大小与是否添加文字
效果如下:
调用代码:
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" 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的代码:
var 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.fill ; // 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.fill ; 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.fill ; ctx.stroke ; 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.stroke ; 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.fill ; 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 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); };
源代码可以直接使用
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/10089.html
cjava相关文章
- WPF+HTML5混合开发
- w3c标准html5手册_在w3c中规定html决定页面的
- 【学习笔记】HTML5
- HTML5环形音乐播放器详解编程语言
- html5 表单元素示例详解编程语言
- HTML5实现拖放详解编程语言
- HTML5页面点击和左右滑动页面滚动详解编程语言
- 基于html5 localStorage的购物车JS脚本详解编程语言
- 高级HTML5 移动应用框架 Ionic v3.0.0 发布详解编程语言
- HTML5移动端通用css详解编程语言
- html5 video获取实时播放进度的方法详解编程语言
- html5 微信真机调试方法vConsole详解编程语言
- 为什么 Facebook 要将视频从 Flash 全面迁移到 HTML5?
- 利用HTML5的CORS特性绕过httpOnly的限制实现XSS会话劫持
- HTML5 Web SQL 数据库
- HTML5 Canvas
- javascript和HTML5利用canvas构建猜牌游戏实现算法
- 非html5实现js版弹球游戏示例代码