chart
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.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 && 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);
}
}
}, };
chart的更多相关文章
- Chart: Who pays the most in Seattle for software engineers
http://www.geekwire.com/2012/chart-pays-seattle-software-engineers/ Chart: Who pays the most in Seat ...
- Visifire Chart相关属性详解
<vc:Chart x:Name="HourlyChart" Theme="Theme1" Grid.Row="1" xmlns:vc ...
- ASP.NET中的chart控件绑定SQL Server数据库
网上很多的chart控件的实例都没有绑定数据库,经过一番摸索后,终于实现了chart控件绑定数据库. 首先,在Visual Studio中建立一个网站,新建一个WebForm项目,名称为ChartTe ...
- 关于chart.js 设置canvas的宽度为父级元素的宽度的百分百 以及 X轴上面刻度数据太多如何处理
今天在做一个数据统计的界面的时候,需要做折线统计图,在网上找了一圈发现数据统计的插件还是不少的,本着轻量级的的原则选择了Chart.js,后来在做的过程中便遇到两个问题,以此记录下来,和刚刚接触前端的 ...
- 使用C#和Excel进行报表开发(三)-生成统计图(Chart)
有的Web项目选用Excel作为报表方案,在服务器端生成Excel文件,然后传送到客户端,由客户端进行打印.在国内的环境下,相对PDF方式,Excel的安装率应该比pdf阅读器的安装率要高,同时,微软 ...
- Chart.js中文文档-雷达图
雷达图或蛛网图(Radar chart) 简介 A radar chart is a way of showing multiple data points and the variation bet ...
- iOS chart 图表完美解决方案 基于swift
如果打算在app中使用图标功能,这个框架基本能够满足90%的需求 下边是作者的框架的下载地址 ,基于swift2.0 https://github.com/danielgindi/ios-charts ...
- 爱上MVC~图表的使用Chart
回到目录 图表在一个系统中是必须的,MVC架构把它当然是一个扩展集成了进来,通过简单的几句话就可以生成一个风格多样的图表,这给报表的开发带来了很大的方便,大叔的项目中也做了一个测试,把主要的代码贴出来 ...
- WPFTookit Chart 高级进阶
数据源增加SeriesSource 使用方式 <Charting:Chart x:Name="chart" Helper:ChartHelper.DependentValue ...
- WPFTookit Chart 入门
如何使用WPFToolKit Chart private void button1_Click(object sender, EventArgs e) { var s = new Series(); ...
随机推荐
- 启动PL/SQL Developer 报字符编码不一致错误,Database character set
错误内容: Database character set (AL32UTF8) and Client character set (ZHS16GBK) are different. Character ...
- 深入了解三种针对文件(JSON、XML与INI)的配置源
深入了解三种针对文件(JSON.XML与INI)的配置源 物理文件是我们最常用到的原始配置的载体,最佳的配置文件格式主要由三种,它们分别是JSON.XML和INI,对应的配置源类型分别是JsonCon ...
- C++之------回调函数
一:What?(什么是回调函数) 回调函数图文讲解 谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数. 例如Win32 ...
- 序列化类型为“System.Reflection.Module”的对象时检测到循环引用
在使用ajax调用web services时,正好返回的类型为datatable,想用通过json方式直接解析,但调用后,得到如下错误: 序列化类型为“System.Reflection.Module ...
- 【Xamarin挖墙脚系列:代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧(转)】
正愁如何选择构建项目中的视图呢,现在官方推荐画板 Storybord...但是好像 xib貌似更胜一筹.以前的老棒子总喜欢装吊,用代码写....用代码堆一个HTML页面不知道你们尝试过没有.等页面做出 ...
- WPF制作的一个小功能,智能提示(IntelliSense)
原文http://www.cnblogs.com/scheshan/archive/2012/06/30/2570867.html 最近WPF项目中遇到一个需求,需要给一个RichTextBox添加智 ...
- 关于DLL模块导出函数
当然以前我知道有一个.def文件的,里面写的都是需要导出的函数,以为与__declspec(dllexport)作用是一样的.但是今天看公司项目源码的时候才知道,它们两个导出方法是有一定的区别的,编译 ...
- 【斗地主技巧】斗地主算法逻辑中的天之道<转>
******************************************************************** 作者比较喜欢玩斗地主,所以经常搜集一些网友斗地主的心得,下面这 ...
- 修改MySQL 5.5的max_allowed_packet属性的方法
今天在部署一个实验系统的时候,报出下面这个错: Your 'max_allowed_packet' variable is set to less than 16777216 Byte (16MB). ...
- [转]Activemq管理和基本介绍
1.ActiveMQ服务器工作模型 通过ActiveMQ消息服务交换消息.消息生产者将消息发送至消息服务,消息消费者则从消息服务接收这些消息.这些消息传送操作是使用一组实现 ActiveM ...