纯HTML5 Canvas实现的饼图
admin
2023-06-11 12:00:26
0

基本思路:

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

context.arc与lineto两个API。

实现的功能有:

1. 支持标签Legend显示或者隐藏

2. 首次载入动画效果

3. 鼠标tooltip效果

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

效果如下:

纯HTML5 Canvas实现的饼图

调用代码:

     My Demo 1 	   

Pie Chart Demo

饼图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 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源代码可以直接使用

相关内容

热门资讯

想去海边过盛夏!华为nova ... 就在刚刚华为终端正式官宣了nova 16系列及全场景新品发布会。说实话,我第一眼看到视频的时候,还真...
华为突破半导体规则引爆中国芯片... 快科技5月25日消息,今天在电气电子工程师学会IEEE主办的2026国际电路与系统研讨会ISCAS现...
宁德,被主机厂“逼”着投Dee... 文 | 超聚焦 DeepSeek的绯闻东家,多了一个宁王。 5月23日,据The Informat...
武契奇被授予“友谊勋章” 5月25日,中华人民共和国“友谊勋章”颁授仪式在北京举行。塞尔维亚总统武契奇被授予“友谊勋章”。(摄...
起底煤矿“暗面”:假整改、假密... 5月22日,山西长治市沁源县通洲集团留神峪煤矿发生瓦斯爆炸,造成82人死亡、2人失联、128人受伤。...
AI驱动文化产业发展:无论技术... 2026文化强国建设高峰论坛人工智能驱动文化产业创新发展论坛22日在深圳举行。与会嘉宾聚焦“AI重构...
原创 美... 原创首发 | 金角财经(ID: F-Jinjiao) 作者 | Chester 中美机器人,到底谁更...
小米SU7现身西班牙塞维利亚 ... 【CNMO科技消息】5月25日,有外媒报道称,近日一辆小米SU7现身西班牙塞维利亚。有技术人士在车内...
从“数字门牌”到“智能入口” ... 人民网记者 黄盛 “十五五”时期,在“人工智能+”行动全面实施的过程中,中文域名如何借助AI技术实现...
通讯|在意大利比萨的实验室看人...   新华社意大利比萨5月25日电 通讯|在意大利比萨的实验室看人与机器人“共生”   新华社记者刁泽...