温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

基于VML与HTML5 Canva实现的跨浏览器饼图与折线图

发布时间:2020-06-25 22:27:05 来源:网络 阅读:297 作者:gloomyfish 栏目:移动开发

本来想自己做个库的,毅力不够啊基于VML与HTML5 Canva实现的跨浏览器饼图与折线图,所以放出源代码

当前实现的框架功能有:

1. 支持IE6+以上版本,支持Chrome, 支持FireFox

2. 动画加载机制

3. tooltip支持

4. legend支持

5. 功能丰富的参数设置

当前支持的图形种类有两种:饼图与折线图,将来也许会不定期更新,不断完善!

希望还有点毅力和时间做话。不废话啦,直接上效果图:

基于VML与HTML5 Canva实现的跨浏览器饼图与折线图

折线图演示代码:

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="js/fishchart.js"></script> <title>Line Demo</title> 	<script> 	window.onload = function() { 		var container = document.getElementById("my_container"); 		var seriesData = [{name:"本一", data:[330,348,355,345, 350, 348], color:"RGB(255,0,0)"}, 		              {name:"本二", data:[300,326,328,320, 330, 325], color:"RGB(0,0,255)"}, 		              {name:"本三", data:[248,288,277,290, 280, 290], color:"RGB(255,0,255)"}]; 		var config = { 				type : "line", 				width : 800,  				height: 400, 				series: seriesData, 				container: container, 				title:"江苏省2008~2013高考录取分数线", 				tooltip : { 					enable : true 				}, 				animation :{ 					enable: true 				}, 			    legend : { 			    	enable : true 			    }, 			     			    yAxis :{ 			    	tickSize: 10, 			    	title: "分数" 			    }, 			    xAxis :{ 			    	tickSize: 10, 			    	title: "年份", 			    	categories: ["2008", "2009", "2010", "2011", "2012", "2013"] 			    } 		}; 		fishChart.initSettings(config); 		fishChart.render(); 	} 	</script> </head> <body> <h2>VML Line Chart Demo</h2> <div id="my_container" style="width:600px; height:400px;"> </div> </body> </html>
饼图演示代码:

<html> <head> <script src="js/fishchart.js"></script> <title>My Demo 1</title> 	<script> 	window.onload = function() { 		var container = document.getElementById("my_container"); 		var seriesData = [{name:"apples", value:150, color:"RGB(255,0,0)"}, 			              {name:"orange", value:100, color:"RGB(255,255,0)"}, 			              {name:"banana", value:80, color:"RGB(255,0,255)"}, 			              {name:"peaches", value:60, color:"RGB(0,255,255)"}, 			              {name:"strawberries", value:40, color:"RGB(0,127,255)"}] 		var config = { 				type : "pie", 				width : 600,  				height: 400, 				series: seriesData, 				container: container, 				unit: "kg", 				title:"Fruit Sales",  				tooltip : { 					enable : true 				}, 				animation :{ 					enable: true 				}, 			    legend : { 			    	enable : true 			    }, 			    text : { 			    	enable: true 			    } 		}; 		fishChart.initSettings(config); 		fishChart.render(); 	} 	</script> </head> <body> <h2>farchart - Pie Demo</h2> <div id="my_container" style="width:600px; height:400px;"> </div> </body> </html>
JS库源代码:有兴趣者可以自己添加更多图表支持
// farchart farchart.js version 0.0.1, 28 August 2013   // (c) 2013 by Jia ZhiGang. All Rights reserved.  // Copyright (c) 2013 Jia ZhiGang (http://www.edinme.com) // // far chart is freely distributable under the terms of an GPL-style license. //  // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: //  // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // For details, see the farchart web site: http://www.edinme.com function check_vmlCapability() { 	if(document.namespaces['v']==null) { 		var e=["shape","shapetype","group","background","path","formulas","handles","fill","stroke","shadow","textbox","textpath","imagedata","line","polyline","curve","roundrect","oval","rect","arc","image"],s=document.createStyleSheet();  		for(var i=0; i<e.length; i++) {s.addRule("v\\:"+e[i],"behavior: url(#default#VML); display: inline-block;");} document.namespaces.add("v","urn:schemas-microsoft-com:vml"); 	}  }  function msieversion() {    var ua = window.navigator.userAgent;    var msie = ua.indexOf ( "MSIE " );     if ( msie > 0 )     { 	   // If Internet Explorer, return version number 	   return parseInt (ua.substring (msie+5, ua.indexOf (".", msie )));	       }          else    { 		// If another browser, return 0	    		return 0; 	}                 }  var fishChart = { 	type: "null", // global flag, default     width: 600,     height: 400,     series: [],     unit: "kg",     container: null, 	title: { 		text: "Far Chart", 		x: -100 // center offset 	},     isIE: true,     legend : {     	enable : true     },     edge : {     	width: 50, // for pie     	height: 50, // for pie 		left: 50, // for other plot 		upper: 40, 		bottom: 40, 		right: 60     }, 	yAxis: { 		title: "Y Axis", 		vgap: 0, 		plotHeight: 0, 		min: 0, 		max: 0, 		tickSize: 10, 		padding: 5 	}, 	xAxis: { 		categories: [], 		tickSize : 10, 		autoTick:true, 		xgap : 0, 		min:0, 		max:0, 		title:"X Axis" 	},     animation: {     	enable: true,     	hh: 1, 		animCanvas:null, 		pctx: null     },     tooltip: {     	enable: true,     	tooltipCanvas : null,     	ttContext: null,     	index: -1     },     circle : { // for pie     	cx: 0,     	cy: 0,     	radius: 0     	     },     text : { // for pie     	enable: false,     	content:[]     },      	point : { // for line and scatter plot 		enable : true, 		radius : 4 	},          initSettings: function (config) {     	this.type = config.type;     	this.container = config.container;         this.width = config.width;         this.height = config.height;         this.series = config.series;         this.title.text = config.title;         this.unit = config.unit;                  // tool-tip, animation, legend setting data         if(config.tooltip != undefined) {         	this.tooltip.enable = config.tooltip.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;         }                  // edge setting data         if(config.edge != undefined && config.edge.right != undefined) {         	this.edge.right = config.edge.right;        	         }         if(config.edge != undefined && config.edge.left != undefined) {         	this.edge.left = config.edge.left;        	         }         if(config.edge != undefined && config.edge.bottom != undefined) {         	this.edge.bottom = config.edge.bottom;        	         }         if(config.edge != undefined && config.edge.upper != undefined) {         	this.edge.upper = config.edge.upper;        	         }                  // xAxis setting         if(config.xAxis != undefined) {        	         	this.xAxis.title= config.xAxis.title;         	this.xAxis.tickSize = config.xAxis.tickSize;         }                  if(config.xAxis != undefined && config.xAxis.categories != undefined) {         	this.xAxis.categories = config.xAxis.categories;         }                  // yAxis setting         if(config.yAxis != undefined) {         	this.yAxis.title = config.yAxis.title;         	this.yAxis.tickSize = config.yAxis.tickSize;        	         }                   // decide whether render plot using HTML5 Canvas or VML         if(msieversion() == 0) {         	this.chartCanvas = document.createElement("canvas");         	this.chartCanvas.id = "fc_canvas";         	this.container.appendChild(this.chartCanvas);         	this.chartCanvas.width = config.width;         	this.chartCanvas.height = config.height;         	this.isIE = false;         } else {         	check_vmlCapability();         	this.isIE = true;         }     },          render : function() {    	     	var ctx = this.getCanvasContext();     	this.renderBorder(ctx);     	if(this.type === "pie") {         	// 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);         	if(this.circle.radius <= 0) {         		console.log("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         	this.customFillText(ctx, this.width/2 - this.edge.width, (this.isIE ? 10 : 30), this.circle.radius, 40, this.title.text, "white", "white", "black", '18pt Calibri');         	         	if(this.isIE) {         		this.renderPieShadow(ctx);         	}         	         	// render bar         	var start = 0;         	for(var i=0; i<nums; i++) {         		var precent = this.series[i].value/sum;         		this.renderPie(ctx, i, start, precent);         		if(this.isIE) {         			start += precent;         		} else {         			start += 2*Math.PI * precent;        			         		}         	}         	         	// post add blur shadow         	if(!this.isIE) {         		this.renderPieShadow(ctx);         	}         	         	// render legend         	this.renderPieLegend(ctx, sum);         	     	}      	// line plot     	else if(this.type == "line")     	{     		     		// draw title     		this.customFillText(ctx, (this.width/2 + this.title.x), (this.isIE ? 2 : this.edge.upper/2), this.width/2, 0, this.title.text, "white", "white", "black", '18pt Calibri');     		// draw XY Axis     		this.renderXYAxis(ctx);     		// draw lines         	var nums = this.series.length;         	for(var i=0; i<nums; i++) {         		this.renderOneLineCurve(ctx, i);         	}         	     		     	}     	     	// render legend     	this.renderLegend(ctx);     	     	// enable tool-tip     	if(this.tooltip.enable && !this.isIE && !this.animation.enable) {     		var parent = this;     		this.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, ctx);     		}, false);            	     	}     	     	// enable animation     	if(this.animation.enable) {     		var parent = this;     		if(this.isIE) {     			ctx.insertBefore(this.animation.animCanvas);	     		}     		setTimeout(function() {parent.playAnimation(parent);}, 1000/20);   	         	}     },          renderOneLineCurve : function(ctx, index) {     	var size = this.series[index].data.length;     	var plotwidth = this.width - this.edge.left - this.edge.right; 		var deltax = plotwidth/size; 		var xpos = this.edge.left; 		 		if(this.isIE) { 			var vpolyLine = document.createElement("v:polyline"); 			vpolyLine.strokecolor=this.series[index].color; 			vpolyLine.id = "vml-fline-" + index; 			vpolyLine.filled="false"; // default is true, will fill area of close path 			var points = ""; 			for(var i=0; i<size; i++) { 				var value = this.series[index].data[i]; 				var deltay = Math.floor((value - this.yAxis.min) * this.yAxis.ygap); 				 				// highlight the data point by circle. 				if(this.point.enable) { 					var hvoval = document.createElement("v:oval"); 					hvoval.style.left = (xpos + Math.floor(deltax/2) - this.point.radius); 					hvoval.style.top = (this.height - this.edge.bottom - deltay - this.point.radius); 					hvoval.style.width = (this.point.radius * 2) + "px"; 					hvoval.style.height = (this.point.radius * 2) + "px"; 					hvoval.strokecolor = this.series[index].color; 					hvoval.fillcolor = this.series[index].color; 					hvoval.title = this.xAxis.categories[i] + " " + this.series[index].name + " : " +  + value; // tool-tip 					ctx.insertBefore(hvoval); 				} 				// - end it				 				 				points += (xpos + Math.floor(deltax/2)) + "," + (this.height - this.edge.bottom - deltay) + " ";		 				xpos += deltax; 			} 			vpolyLine.strokeweight="1px"; 			vpolyLine.points=points; 			ctx.insertBefore(vpolyLine); 		}  		else  		{ 			ctx.save(); 			ctx.beginPath(); 			ctx.lineWidth = 1; 			for(var i=0; i<size; i++) { 				var value = this.series[index].data[i]; 				var deltay = Math.floor((value - this.yAxis.min) * this.yAxis.ygap); 				ctx.strokeStyle=this.series[index].color; 				if(i == 0) { 					ctx.moveTo(xpos + Math.floor(deltax/2), this.height - this.edge.bottom - deltay); 				} else { 					ctx.lineTo(xpos + Math.floor(deltax/2), this.height - this.edge.bottom - deltay); 				} 				 				xpos += deltax; 			}    	 			ctx.stroke(); 			ctx.restore(); 			 			// draw dot circle 			if(!this.point.enable) 				return; 			ctx.save(); 			var xpos = this.edge.left; 			for(var i=0; i<size; i++) { 				var value = this.series[index].data[i]; 				var deltay = Math.floor((value - this.yAxis.min) * this.yAxis.ygap); 				ctx.beginPath(); 				ctx.arc(xpos + Math.floor(deltax/2), this.height - this.edge.bottom - deltay, this.point.radius, 0, 2*Math.PI, false); 				ctx.closePath(); 				ctx.fillStyle=this.series[index].color; 				ctx.fill(); 				xpos += deltax; 			} 			ctx.restore(); 		}     },          renderPieLegend : 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;     		this.renderRect(ctx, (pos - 40), (20*i+10), 10, 10, this.series[i].color, this.series[i].color, 0);     		this.customFillText(ctx, (pos - 25), (this.isIE ? (20*i + 1) : (20*i+20)), 100, 0, tipStr, "white", "white", "black", "10pt Calibri");     	}      },          renderPieShadow  : function(ctx) {     	if(this.isIE) {         	var voval = document.createElement("v:oval");         	voval.style.left=(this.circle.cx - this.circle.radius) + "px";         	voval.style.top=(this.circle.cy - this.circle.radius) + "px";         	voval.style.width=this.circle.radius*2 + "px";         	voval.style.height=this.circle.radius*2 + "px";         	voval.style.position="absolute";         	voval.strokecolor="RGB(150,150,150)";         	voval.strokeweight="4pt";         	ctx.insertBefore(voval);     	} else {         	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();     	}     },          renderPie : function(ctx, index, startp, precent) {     	if(this.isIE) {         	var start = Math.round (startp*100);          	var end = Math.round (precent*100) + start;         	var part = document.createElement("v:shape");         	part.style.width=Math.min(this.width, this.height) + "px";         	part.style.height=Math.min(this.width, this.height) + "px";         	part.style.position="absolute";         	part.id = "vml-pie-part-" + index;         	var path = "";         	for (var i= start; i <= end; i++) {     	      x = Math.floor((Math.cos(i*Math.PI/50)*this.circle.radius)+this.circle.cx);     	      y = Math.floor((Math.sin(i*Math.PI/50)*this.circle.radius)+this.circle.cy);     	      xs = x.toString();     	      ys = y.toString();     	      path +=  xs + ", " + ys + ", ";         	}         	part.strokecolor=this.series[index].color;         	part.strokeweight="0pt";         	part.fillcolor = this.series[index].color;         	part.path= "m " + this.circle.cx + "," + this.circle.cy +" l " + path + this.circle.cx + "," + this.circle.cy + " x e";         	ctx.insertBefore(part);         	         	// render text content     		if(this.text.enable) {    		     			var textLine = document.createElement("v:line");     			var fx = Math.floor((Math.cos((start + (end - start)/2)*Math.PI/50)*this.circle.radius)+this.circle.cx);     			var fy = Math.floor((Math.sin((start + (end - start)/2)*Math.PI/50)*this.circle.radius)+this.circle.cy);     			var tx = (fx < this.circle.cx) ? (fx - this.edge.width) : (fx + this.edge.width);     			textLine.from = fx + "," + fy;     			textLine.to = tx + "," + fy;     			ctx.insertBefore(textLine);     			     			var textPos = (fx < this.circle.cx) ? (fx - this.edge.width*2) : (fx + this.edge.width);    			     			this.customFillText(ctx, (textPos), (fy-20), 100, 0, this.series[index].name + ": " + (precent * 100).toFixed(0) + "%", "white", "white", "black", "10pt Calibri");     		}     		     		if(this.tooltip.enable) {     			var _parent = this;     			part.title = "Index: " + (index + 1) + "\n" + this.series[index].name + ": " + this.series[index].value + this.unit + "\n" +      						this.series[index].name + ": " + (precent * 100).toFixed(0) + "%" + "\n";     			part.attachEvent(' function (event) {     				var srcElement = event.srcElement;     				srcElement.strokecolor= "white";     				srcElement.strokeweight="3pt";     			});     			part.attachEvent(' function (event) {      				var srcElement = event.srcElement;     				srcElement.strokecolor=_parent.series[index].color;     				srcElement.strokeweight="0pt";     			});     		}     		     	} else {    		     		var endAngle = startp + 2*Math.PI*precent;     		ctx.save();     		ctx.beginPath();     		ctx.arc(this.circle.cx, this.circle.cy, this.circle.radius, startp, endAngle, false);     		ctx.moveTo(this.circle.cx, this.circle.cy);     		ctx.lineTo(this.circle.cx + this.circle.radius * Math.cos(startp), this.circle.cy + this.circle.radius * Math.sin(startp));     		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.strokeStyle = this.series[index].color;     		ctx.fill();     		ctx.stroke();     		ctx.restore();     		         	// render text content         	if(this.text.enable) {    		         		var halfEndAngle = startp + 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);         	}     	}     },          showLineTooltips : function(loc, ctx) {     	if(!this.tooltip.enable) {     		return;     	}     	var size = this.series[0].data.length;     	var plotwidth = this.width - this.edge.left - this.edge.right; 		var deltax = (plotwidth/ size);     	var xunit = ((loc.x - this.edge.left)/deltax); //: */loc.x - this.edge.left;     	var deltay = this.height - this.edge.bottom - loc.y;     	if(xunit > 0 && deltay > 0) {     		var value = deltay/this.yAxis.ygap + this.yAxis.min;     		var xindex = Math.floor(xunit);     		var xpoint = xunit - xindex;     		if(xpoint < 0.55 && xpoint >0.45) {     			var num = this.series.length;     			var distance = [];     			for(var i=0; i<num; i++) {     				var dis = this.series[i].data[xindex] - value;     				distance[i] = Math.abs(dis);     			}     			var min = distance[0];     			var yindex = 0;     			for(var i=0; i<num; i++) {     				if(min > distance[i]) {     					min = distance[i];     					yindex = i;     				}     			}     			     			if(this.series[yindex].data[xindex] > Math.floor(value - 3) && this.series[yindex].data[xindex] < Math.floor(value + 3) ) {     				this.renderLineTooltips(ctx, yindex, xindex, loc);     			}      			// clear tool tip     			else {     				this.clearTooltips(ctx);     			}     		}      		else {     			this.clearTooltips(ctx);     		}     	}      	else {     		this.clearTooltips(ctx);     	}     },          renderLineTooltips : function(ctx, yindex, xindex, loc) { 		// show tool tip 		this.clearTooltips(ctx); 		if(this.tooltip.tooltipCanvas == null) { 			this.tooltip.tooltipCanvas = document.createElement("canvas"); 			this.tooltip.ttContext = this.tooltip.tooltipCanvas.getContext("2d");     		this.tooltip.tooltipCanvas.width = 150;     		this.tooltip.tooltipCanvas.height = 100; 		} 		var m_context = this.tooltip.ttContext; 		m_context.save(); 		m_context.clearRect(0, 0, this.tooltip.tooltipCanvas.width, this.tooltip.tooltipCanvas.height); 		m_context.lineWidth = 2; 		m_context.strokeStyle = this.series[yindex].color; 		m_context.fillStyle="RGBA(255,255,255,0.7)"; 		this.getRoundRect(m_context, 2,2,this.tooltip.tooltipCanvas.width-4, this.tooltip.tooltipCanvas.height-4, 5, true, true); 		m_context.font="14px Arial"; 		m_context.fillStyle="RGBA(0,0,0,1)"; 		if(this.type == "line") { 			m_context.fillText((this.xAxis.title + ": " + this.xAxis.categories[xindex]), 5, 20); 			m_context.fillText(this.series[yindex].name + ": " + this.series[yindex].data[xindex], 5, 40);			 		} else { 			m_context.fillText(this.series[yindex].name, 5, 20); 			m_context.fillText(this.xAxis.title + ":" + this.series[yindex].data[xindex][0], 5, 40); 			m_context.fillText(this.yAxis.title + ":" + this.series[yindex].data[xindex][1], 5, 60); 		} 		m_context.restore(); 		 		// make tool-tip rectangle is always visible  		if((loc.x + this.tooltip.tooltipCanvas.width)> this.width) { 			loc.x = loc.x - this.tooltip.tooltipCanvas.width; 		} 		if((loc.y - this.tooltip.tooltipCanvas.height) <= 0) { 			loc.y = loc.y + this.tooltip.tooltipCanvas.height; 		} 		ctx.drawImage(this.tooltip.tooltipCanvas, 0, 0, this.tooltip.tooltipCanvas.width, this.tooltip.tooltipCanvas.height,  				loc.x, loc.y-this.tooltip.tooltipCanvas.height, this.tooltip.tooltipCanvas.width, this.tooltip.tooltipCanvas.height);     },          showPieTooltips : function(loc, ctx) {     	if(!this.tooltip.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.tooltip.tooltipCanvas == null) {     			this.tooltip.tooltipCanvas = document.createElement("canvas");     			this.tooltip.ttContext = this.tooltip.tooltipCanvas.getContext("2d");         		this.tooltip.tooltipCanvas.width = 150;         		this.tooltip.tooltipCanvas.height = 100;     		}      		     		// only draw once     		// if(index == this.tooltips.index){     		// 	return;     		// }     		this.clearTooltips(ctx);     		     		this.tooltip.index = index;     		var m_context = this.tooltip.ttContext;     		m_context.save();     		m_context.clearRect(0, 0, this.tooltip.tooltipCanvas.width, this.tooltip.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);     		this.getRoundRect(m_context, 2,2,this.tooltip.tooltipCanvas.width-4, this.tooltip.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.tooltip.tooltipCanvas.width)> this.width) { 				loc.x = loc.x - this.tooltip.tooltipCanvas.width; 			} 			if((loc.y - this.tooltip.tooltipCanvas.height) <= 0) { 				loc.y = loc.y + this.tooltip.tooltipCanvas.height; 			} 			ctx.drawImage(this.tooltip.tooltipCanvas, 0, 0, this.tooltip.tooltipCanvas.width, this.tooltip.tooltipCanvas.height,  					loc.x, loc.y-this.tooltip.tooltipCanvas.height, this.tooltip.tooltipCanvas.width, this.tooltip.tooltipCanvas.height);	     	} else {     		this.tooltip.index = -1;     		this.clearTooltips(ctx);     	}     },          redrawPie : function(ctx) {     	if(this.animation.enable) {     		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);      	} else {         	// 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         	this.customFillText(ctx, this.width/2 - this.edge.width, (this.isIE ? 10 : 30), this.circle.radius, 40, this.title, "white", "white", "black", '18pt Calibri');         	         	if(this.isIE) {         		this.renderPieShadow(ctx);         	}         	         	// render bar         	var start = 0;         	for(var i=0; i<nums; i++) {         		var precent = this.series[i].value/sum;         		this.renderPie(ctx, i, start, precent);         		if(this.isIE) {         			start += precent;         		} else {         			start += 2*Math.PI * precent;        			         		}         	}         	         	// post add blur shadow         	if(!this.isIE) {         		this.renderPieShadow(ctx);         	}         	         	// render legend         	this.renderPieLegend(ctx, sum);     	}     },          renderXYAxis : function(ctx) {     	this.drawXYTitles(ctx);     	if(this.type == "line") {         	// draw ticks and markers         	var nums = this.series.length;         	if(nums == 0) return;     		     		var min = 0;     		var max = 0;     		min = this.series[0].data[0];     		max = this.series[0].data[0];     		for(var s = 0; s < nums; s++) {     			var size = this.series[s].data.length;     			for(var i=0; i<size; i++) {     				min = Math.min(min, this.series[s].data[i]);     				max = Math.max(max, this.series[s].data[i]);     			}     		}    		         	         	// calculate the text gap in Y Axis         	var delta = max - min;         	this.yAxis.padding = delta/10;         	this.yAxis.min = min - this.yAxis.padding;         	this.yAxis.max = max + this.yAxis.padding;         	var sum = this.yAxis.max - this.yAxis.min;         	var plotHeight = this.height - this.edge.upper - this.edge.bottom;         	var ygap = plotHeight/sum;         	this.yAxis.plotheight = plotHeight;         	this.yAxis.ygap = ygap;         	var index = Math.floor(this.yAxis.min);         	var first = true;     		// draw Y Axis and dash line         	for(var ypos=0; ypos<(plotHeight + this.edge.upper/2); ypos+=ygap*this.yAxis.tickSize)         	{         		this.customFillText(ctx, this.isIE ? (this.edge.left/3) : this.edge.left/2, this.isIE ? (this.height - this.edge.bottom - Math.floor(ypos)-15) : this.height - this.edge.bottom - Math.floor(ypos),          				40, 0, "" + index, "white", "white", "black", "10px Arial");         		index = index + this.yAxis.tickSize;         		         		// draw dash line         		if(!first) {         			this.dashedLineTo(ctx, this.edge.left, this.height - this.edge.bottom - Math.floor(ypos), this.width - this.edge.right, this.height - this.edge.bottom - Math.floor(ypos), 5);        				       			         		}         		first = false;         	}         	         	// draw X Axis sub title     		var csize = this.xAxis.categories.length;     		var plotwidth = this.width - this.edge.left - this.edge.right;     		delta = plotwidth/ csize;     		var xpos = this.edge.left;     		for(var x=0; x<csize; x++) {     			this.customFillText(ctx, (xpos + delta/2), this.isIE ? (this.height - (this.edge.bottom*0.75) - 15):this.height - (this.edge.bottom*0.75),      					50, 0, this.xAxis.categories[x], "white", "white", "black", "10px Arial");     			xpos += delta;     		}         	     	} else if(this.type == "scatter") {     		     	} else if(this.type == "column") {     		     	} else if(this.type == "bar") {     		     	}     },          drawXYTitles : function(ctx) {     	if(this.isIE) {         	// draw X Axis and title         	var xLine = document.createElement("v:line");         	xLine.from = this.edge.left + "," + (this.height-this.edge.bottom);         	xLine.to = (this.width - this.edge.right) + "," + (this.height-this.edge.bottom);         	ctx.insertBefore(xLine);         	this.customFillText(ctx, this.width/2, this.height-this.edge.bottom/2, (this.width/2 - this.edge.right), 0, this.xAxis.title, "white", "white", "black", "12px Arial");          	// draw Y title, VML rotate text is very trick thing,     		// the center point is itself half of width and height, very bad way     		var yTitleRect = document.createElement("v:rect");     		yTitleRect.style.left= Math.floor(-this.height/2 + 10) + "px";     		yTitleRect.style.top= (this.height - this.edge.bottom) + "px";     		yTitleRect.style.width=Math.floor(this.height) + "px";     		yTitleRect.style.height="0px";     		yTitleRect.fillcolor = "white";     		yTitleRect.strokecolor="white";     		yTitleRect.strokeweight="0pt";     		     		var ytitleTextBox = document.createElement("v:textbox");     		ytitleTextBox.style.font = "12px Arial";     		ytitleTextBox.innerText = this.yAxis.title;     		yTitleRect.style.rotation = "90"; // only make the text vertical, bad!!!     		yTitleRect.insertBefore(ytitleTextBox);		     		ctx.insertBefore(yTitleRect);     		     	} else {     		// draw X Axis and title     		ctx.save();     		this.onePixelLineTo(ctx, this.edge.left, this.height-this.edge.bottom, this.width - this.edge.right, this.height-this.edge.bottom, "white", false);  	     		ctx.restore();     		ctx.font="12px Arial";     		ctx.fillText(this.xAxis.title, this.width/2, this.height-this.edge.bottom/4);     		     		// draw Y title     		ctx.save();     		ctx.font="12px Arial";     		ctx.translate(this.width/2, this.height/2);     		ctx.rotate(-Math.PI/2);     		ctx.fillText(this.yAxis.title, 20, -(this.width/2 - 20));     		ctx.restore();    		     	}     },          renderLegend : function(ctx) {     	if(!this.legend.enable || this.type == "pie") {     		return;     	}     	// TODO:zhigang, legend here     },          renderBorder : function(ctx) {     	this.renderRect(ctx, 0, 0, this.width, this.height, "white", "black", 1);     },          playAnimation : function(parent) {     	     	if(parent.animation.hh < parent.height) {     		if(parent.isIE) {     			var node = document.getElementById("fishchart_mask_rect");     			node.style.top= this.animation.hh + "px";     			node.style.height= (this.height - this.animation.hh) + "px";     			parent.animation.hh = parent.animation.hh + 10;     			setTimeout(function() {parent.playAnimation(parent);}, 1000/20);     		} else {     			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 {     		// remove xxxxx or change the alpha value     		if(parent.isIE) {    			     	    	var node = document.getElementById("fishchart_mask_rect");     	    	if(node != null) { 	    		     	    		parent.animation.pctx.removeChild(node);    		     	    	}     	    	     		} 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(!this.isIE && parent.animation.enable && parent.tooltip.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)};     	    		console.log("ddddddddddddddddddddd");     	    		parent.showTooltips(loc, (parent.animation.enable ? parent.animation.pctx : ctx));     	        }, false);         	}     	}     },          clearTooltips : function(ctx) { 		if(this.animation.enable) { 			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); 			 		} else {			 			this.redrawPlot(ctx); 		}     },          redrawPlot : function(ctx) {     	if(this.type === "pie") {     		this.redrawPie(ctx);     	} else if(this.type == "line") {     		ctx.clearRect(0,0,this.width, this.height);     		// draw title     		this.customFillText(ctx, (this.width/2 + this.title.x), (this.isIE ? 2 : this.edge.upper/2), this.width/2, 0, this.title.text, "white", "white", "black", '18pt Calibri');     		// draw XY Axis     		this.renderXYAxis(ctx);     		// draw lines         	var nums = this.series.length;         	for(var i=0; i<nums; i++) {         		this.renderOneLineCurve(ctx, i);         	}     	}     },          showTooltips : function(loc, ctx) {     	if(this.type === "pie") {     		this.showPieTooltips(loc, ctx);     	} else if(this.type === "line") {     		this.showLineTooltips(loc, ctx);     	}     },          getCanvasContext : function() {     	var ctx = null;     	if(this.isIE) {     		// create group     		ctx = document.createElement("v:group");     		var min_size = Math.min(this.width, this.height);     		ctx.style.width = min_size;     		ctx.style.height = min_size;     		     		// default the group will be center inside the DIV element     		ctx.coordsize = min_size + ' ' + min_size;     		this.container.insertBefore(ctx);     		if(this.animation.enable) {     			this.animation.animCanvas = document.createElement("v:rect");     			this.animation.animCanvas.id = "fishchart_mask_rect";     			this.animation.animCanvas.style.left= "0px";     			this.animation.animCanvas.style.top= "0px";     			this.animation.animCanvas.style.width= this.width + "px";     			this.animation.animCanvas.style.height= this.height + "px";     			this.animation.animCanvas.fillcolor = "white";     			this.animation.animCanvas.strokecolor = "white";     			this.animation.animCanvas.strokeweight= "0pt";     			var ttfill = document.createElement("v:fill");     			ttfill.opacity = "100%";     			this.animation.animCanvas.insertBefore(ttfill);	     			this.animation.pctx = ctx;     		}     	} else {         	if(this.animation.enable) {         		this.animation.animCanvas = document.createElement("canvas");             	this.animation.animCanvas.width = this.width;             	this.animation.animCanvas.height = this.height;             	this.animation.pctx = this.chartCanvas.getContext("2d"); // parent ctx             	ctx = this.animation.animCanvas.getContext("2d");         	} else {         		ctx = this.chartCanvas.getContext("2d");         	}     	}     	return ctx;     },          getRoundRect : function(ctx, x, y, width, height, radius, fill, stroke) { 		if (typeof stroke == "undefined") { 			stroke = true; 		} 		if (typeof radius === "undefined") { 			radius = 5; 		} 		ctx.beginPath(); 		ctx.moveTo(x + radius, y); 		ctx.lineTo(x + width - radius, y); 		ctx.quadraticCurveTo(x + width, y, x + width, y + radius); 		ctx.lineTo(x + width, y + height - radius); 		ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y+ height); 		ctx.lineTo(x + radius, y + height); 		ctx.quadraticCurveTo(x, y + height, x, y + height - radius); 		ctx.lineTo(x, y + radius); 		ctx.quadraticCurveTo(x, y, x + radius, y); 		ctx.closePath(); 		if (stroke) { 			ctx.stroke(); 		} 		if (fill) { 			ctx.fill(); 		}     },          renderRect : function (ctx, x, y, width, height, fillColor, strokeColor, lineWidth)      {     	if(this.isIE) {     		var vrect = document.createElement("v:rect");     		vrect.style.left= x + "px";     		vrect.style.top= y + "px";     		vrect.style.width= width + "px";     		vrect.style.height= height + "px";     		vrect.fillcolor = fillColor;     		vrect.strokecolor=strokeColor;     		vrect.strokeweight= lineWidth + "pt";     		ctx.insertBefore(vrect);     	} else {     		ctx.save();     		ctx.fillStyle= fillColor;     		ctx.strokeStyle= strokeColor;     		ctx.fillRect(x, y, width, height);     		ctx.strokeRect(x, y, width, height);     		ctx.restore();     	}     },          customFillText : function (ctx, x, y, width, height, textContent, fillColor, strokeColor, fontColor, fontSize)     {     	if(this.isIE) {     		var textRect = document.createElement("v:rect");     		textRect.style.left=(x) + "px";     		textRect.style.top=(y) + "px";     		textRect.style.width=width + "px";     		textRect.style.height=height + "px";     		textRect.fillcolor = fillColor;     		textRect.strokecolor = strokeColor;     		textRect.strokeweight="0pt";     		var textBox = document.createElement("v:textbox");     		textBox.style.font = fontSize;// "10pt Calibri";     		textBox.innerText = textContent;     		 			// make stroke and fill attribute transparent is 100% 			var ttfill = document.createElement("v:fill"); 			ttfill.opacity = "0%"; 			var ttstroke = document.createElement("v:stroke"); 			ttstroke.opacity = "0%"; 			 			// append to group element 			textRect.insertBefore(ttstroke); 			textRect.insertBefore(ttfill);			     		textRect.insertBefore(textBox);     		ctx.insertBefore(textRect);    		     	} else {     		ctx.save();     		ctx.font = fontSize;//'10pt Calibri';     		ctx.fillStyle=fontColor;     		ctx.fillText(textContent, x, y);     		ctx.restore();     	}     },          onePixelLineTo : function(ctx, fromX, fromY, toX, toY, backgroundColor, vertical) {     	var currentStrokeStyle = this.strokeStyle;     	ctx.beginPath();     	ctx.moveTo(fromX, fromY);     	ctx.lineTo(toX, toY);     	ctx.closePath();     	ctx.lineWidth=2;     	ctx.stroke();     	ctx.beginPath();     	if(vertical) {     		ctx.moveTo(fromX+1, fromY);     		ctx.lineTo(toX+1, toY);     	} else {     		ctx.moveTo(fromX, fromY+1);     		ctx.lineTo(toX, toY+1);     	}     	ctx.closePath();     	ctx.lineWidth=2;     	ctx.strokeStyle=backgroundColor;     	ctx.stroke();     	ctx.strokeStyle = currentStrokeStyle;     },          dashedLineTo : function (ctx, fromX, fromY, toX, toY, pattern) { 		if(this.isIE) { 			var vdashline = document.createElement("v:line"); 			var vdashlineStroke = document.createElement("v:stroke"); 			vdashline.from = fromX + "," + fromY; 			vdashline.to = toX + "," + toY; 			vdashlineStroke.dashstyle="dash"; 			vdashline.insertBefore(vdashlineStroke); 			ctx.insertBefore(vdashline);        				 		} else { 	    	ctx.save(); 	    	ctx.lineWidth = 1; 	    	ctx.translate(0.5,0.5); 			// default interval distance -> 5px 	    	if (typeof pattern === "undefined") { 	    		pattern = 5; 	    	} 	 	    	// calculate the delta x and delta y 	    	var dx = (toX - fromX); 	    	var dy = (toY - fromY); 	    	var distance = Math.floor(Math.sqrt(dx*dx + dy*dy)); 	    	var dashlineInteveral = (pattern <= 0) ? distance : (distance/pattern); 	    	var deltay = Math.floor((dy/distance) * pattern); 	    	var deltax = Math.floor((dx/distance) * pattern); 	    	 	    	// draw dash line 	    	ctx.beginPath(); 	    	for(var dl=0; dl<dashlineInteveral; dl++) { 	    		if(dl%2) { 	    			ctx.lineTo(fromX + dl*deltax, fromY + dl*deltay); 	    		} else {    				 	    			ctx.moveTo(fromX + dl*deltax, fromY + dl*deltay);    				 	    		}    			 	    	} 	    	ctx.stroke(); 	    	ctx.restore(); 		}     }      };

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI