1
+ <!DOCTYPE html>
2
+ < html >
3
+ < head lang ="en ">
4
+ < meta charset ="UTF-8 ">
5
+ < title > </ title >
6
+ < style >
7
+ canvas {
8
+ border : 1px solid # A4E2F9 ;
9
+ }
10
+ </ style >
11
+ </ head >
12
+ < body >
13
+ < div height ="400 " width ="600 " style ="margin:50px ">
14
+ < canvas id ="chart "> 你的浏览器不支持HTML5 canvas </ canvas >
15
+ </ div >
16
+
17
+ < script type ="text/javascript ">
18
+ function goChart ( dataArr ) {
19
+
20
+ // 声明所需变量
21
+ var canvas , ctx ;
22
+ // 图表属性
23
+ var cWidth , cHeight , cMargin , cSpace ;
24
+ // 饼状图属性
25
+ var radius , ox , oy ; //半径 圆心
26
+ var tWidth , tHeight ; //图例宽高
27
+ var posX , posY , textX , textY ;
28
+ var startAngle , endAngle ;
29
+ var totleNb ;
30
+ // 运动相关变量
31
+ var ctr , numctr , speed ;
32
+ //鼠标移动
33
+ var mousePosition = { } ;
34
+
35
+ //线条和文字
36
+ var lineStartAngle , line , textPadding , textMoveDis ;
37
+
38
+ // 获得canvas上下文
39
+ canvas = document . getElementById ( "chart" ) ;
40
+ if ( canvas && canvas . getContext ) {
41
+ ctx = canvas . getContext ( "2d" ) ;
42
+ }
43
+ initChart ( ) ;
44
+
45
+ // 图表初始化
46
+ function initChart ( ) {
47
+ // 图表信息
48
+ cMargin = 20 ;
49
+ cSpace = 40 ;
50
+
51
+ canvas . width = canvas . parentNode . getAttribute ( "width" ) * 2 ;
52
+ canvas . height = canvas . parentNode . getAttribute ( "height" ) * 2 ;
53
+ canvas . style . height = canvas . height / 2 + "px" ;
54
+ canvas . style . width = canvas . width / 2 + "px" ;
55
+ cHeight = canvas . height - cMargin * 2 ;
56
+ cWidth = canvas . width - cMargin * 2 ;
57
+
58
+ //饼状图信息
59
+ radius = cHeight * 2 / 6 ; //半径 高度的2/6
60
+ ox = canvas . width / 2 + cSpace ; //圆心
61
+ oy = canvas . height / 2 ;
62
+ tWidth = 60 ; //图例宽和高
63
+ tHeight = 20 ;
64
+ posX = cMargin ;
65
+ posY = cMargin ; //
66
+ textX = posX + tWidth + 15
67
+ textY = posY + 18 ;
68
+ startAngle = endAngle = 90 * Math . PI / 180 ; //起始弧度 结束弧度
69
+ rotateAngle = 0 ; //整体旋转的弧度
70
+
71
+ //将传入的数据转化百分比
72
+ totleNb = 0 ;
73
+ new_data_arr = [ ] ;
74
+ for ( var i = 0 ; i < dataArr . length ; i ++ ) {
75
+ totleNb += dataArr [ i ] [ 0 ] ;
76
+ }
77
+ for ( var i = 0 ; i < dataArr . length ; i ++ ) {
78
+ new_data_arr . push ( dataArr [ i ] [ 0 ] / totleNb ) ;
79
+ }
80
+ totalYNomber = 10 ;
81
+ // 运动相关
82
+ ctr = 1 ; //初始步骤
83
+ numctr = 50 ; //步骤
84
+ speed = 1.2 ; //毫秒 timer速度
85
+
86
+ //指示线 和 文字
87
+ lineStartAngle = - startAngle ;
88
+ line = 40 ; //画线的时候超出半径的一段线长
89
+ textPadding = 10 ; //文字与线之间的间距
90
+ textMoveDis = 200 ; //文字运动开始的间距
91
+ }
92
+
93
+ drawMarkers ( ) ;
94
+ //绘制比例图及文字
95
+ function drawMarkers ( ) {
96
+ ctx . textAlign = "left" ;
97
+ for ( var i = 0 ; i < dataArr . length ; i ++ ) {
98
+ //绘制比例图及文字
99
+ ctx . fillStyle = dataArr [ i ] [ 1 ] ;
100
+ ctx . fillRect ( posX , posY + 40 * i , tWidth , tHeight ) ;
101
+ ctx . moveTo ( posX , posY + 40 * i ) ;
102
+ ctx . font = 'normal 24px 微软雅黑' ; //斜体 30像素 微软雅黑字体
103
+ ctx . fillStyle = dataArr [ i ] [ 1 ] ; //"#000000";
104
+ var percent = dataArr [ i ] [ 2 ] + ":" + parseInt ( 100 * new_data_arr [ i ] ) + "%" ;
105
+ ctx . fillText ( percent , textX , textY + 40 * i ) ;
106
+ }
107
+ } ;
108
+
109
+ //绘制动画
110
+ pieDraw ( ) ;
111
+ function pieDraw ( mouseMove ) {
112
+
113
+ for ( var n = 0 ; n < dataArr . length ; n ++ ) {
114
+ ctx . fillStyle = ctx . strokeStyle = dataArr [ n ] [ 1 ] ;
115
+ ctx . lineWidth = 1 ;
116
+ var step = new_data_arr [ n ] * Math . PI * 2 ; //旋转弧度
117
+ var lineAngle = lineStartAngle + step / 2 ; //计算线的角度
118
+ lineStartAngle += step ; //结束弧度
119
+
120
+ ctx . beginPath ( ) ;
121
+ var x0 = ox + radius * Math . cos ( lineAngle ) , //圆弧上线与圆相交点的x坐标
122
+ y0 = oy + radius * Math . sin ( lineAngle ) , //圆弧上线与圆相交点的y坐标
123
+ x1 = ox + ( radius + line ) * Math . cos ( lineAngle ) , //圆弧上线与圆相交点的x坐标
124
+ y1 = oy + ( radius + line ) * Math . sin ( lineAngle ) , //圆弧上线与圆相交点的y坐标
125
+ x2 = x1 , //转折点的x坐标
126
+ y2 = y1 ,
127
+ linePadding = ctx . measureText ( dataArr [ n ] [ 2 ] ) . width + 10 ; //获取文本长度来确定折线的长度
128
+
129
+ ctx . moveTo ( x0 , y0 ) ;
130
+ //对x1/y1进行处理,来实现折线的运动
131
+ yMove = y0 + ( y1 - y0 ) * ctr / numctr ;
132
+ ctx . lineTo ( x1 , yMove ) ;
133
+ if ( x1 <= x0 ) {
134
+ x2 -= line ;
135
+ ctx . textAlign = "right" ;
136
+ ctx . lineTo ( x2 - linePadding , yMove ) ;
137
+ ctx . fillText ( dataArr [ n ] [ 2 ] , x2 - textPadding - textMoveDis * ( numctr - ctr ) / numctr , y2 - textPadding ) ;
138
+ } else {
139
+ x2 += line ;
140
+ ctx . textAlign = "left" ;
141
+ ctx . lineTo ( x2 + linePadding , yMove ) ;
142
+ ctx . fillText ( dataArr [ n ] [ 2 ] , x2 + textPadding + textMoveDis * ( numctr - ctr ) / numctr , y2 - textPadding ) ;
143
+ }
144
+
145
+ ctx . stroke ( ) ;
146
+
147
+ }
148
+
149
+
150
+
151
+ //设置旋转
152
+ ctx . save ( ) ;
153
+ ctx . translate ( ox , oy ) ;
154
+ ctx . rotate ( ( Math . PI * 2 / numctr ) * ctr / 2 ) ;
155
+
156
+ //绘制一个圆圈
157
+ ctx . strokeStyle = "rgba(0,0,0," + 0.5 * ctr / numctr + ")"
158
+ ctx . beginPath ( ) ;
159
+ ctx . arc ( 0 , 0 , ( radius + 20 ) * ctr / numctr , 0 , Math . PI * 2 , false ) ;
160
+ ctx . stroke ( ) ;
161
+
162
+ for ( var j = 0 ; j < dataArr . length ; j ++ ) {
163
+
164
+ //绘制饼图
165
+ endAngle = endAngle + new_data_arr [ j ] * ctr / numctr * Math . PI * 2 ; //结束弧度
166
+
167
+ ctx . beginPath ( ) ;
168
+ ctx . moveTo ( 0 , 0 ) ; //移动到到圆心
169
+ ctx . arc ( 0 , 0 , radius * ctr / numctr , startAngle , endAngle , false ) ; //绘制圆弧
170
+
171
+ ctx . fillStyle = dataArr [ j ] [ 1 ] ;
172
+ if ( mouseMove && ctx . isPointInPath ( mousePosition . x * 2 , mousePosition . y * 2 ) ) {
173
+ ctx . globalAlpha = 0.8 ;
174
+ }
175
+
176
+ ctx . closePath ( ) ;
177
+ ctx . fill ( ) ;
178
+ ctx . globalAlpha = 1 ;
179
+
180
+ startAngle = endAngle ; //设置起始弧度
181
+ if ( j == dataArr . length - 1 ) {
182
+ startAngle = endAngle = 90 * Math . PI / 180 ; //起始弧度 结束弧度
183
+ }
184
+ }
185
+
186
+ ctx . restore ( ) ;
187
+
188
+ if ( ctr < numctr ) {
189
+ ctr ++ ;
190
+ setTimeout ( function ( ) {
191
+ //ctx.clearRect(-canvas.width,-canvas.width,canvas.width*2, canvas.height*2);
192
+ ctx . clearRect ( - canvas . width , - canvas . height , canvas . width * 2 , canvas . height * 2 ) ;
193
+ drawMarkers ( ) ;
194
+ pieDraw ( ) ;
195
+ } , speed *= 1.085 ) ;
196
+ }
197
+ }
198
+
199
+
200
+
201
+ //监听鼠标移动
202
+ var mouseTimer = null ;
203
+ canvas . addEventListener ( "mousemove" , function ( e ) {
204
+ e = e || window . event ;
205
+ if ( e . offsetX || e . offsetX == 0 ) {
206
+ mousePosition . x = e . offsetX ;
207
+ mousePosition . y = e . offsetY ;
208
+ } else if ( e . layerX || e . layerX == 0 ) {
209
+ mousePosition . x = e . layerX ;
210
+ mousePosition . y = e . layerY ;
211
+ }
212
+
213
+ clearTimeout ( mouseTimer ) ;
214
+ mouseTimer = setTimeout ( function ( ) {
215
+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
216
+ drawMarkers ( ) ;
217
+ pieDraw ( true ) ;
218
+ } , 10 ) ;
219
+ } ) ;
220
+
221
+
222
+
223
+ }
224
+
225
+ var chartData = [ [ 50 , "#2dc6c8" , "瓜子" ] , [ 100 , "#b6a2dd" , "花生" ] , [ 200 , "#5ab1ee" , "土豆" ] , [ 700 , "#d7797f" , "南瓜四号" ] ] ;
226
+
227
+ goChart ( chartData ) ;
228
+
229
+
230
+ </ script >
231
+ </ body >
232
+ </ html >
0 commit comments