@@ -62,7 +62,6 @@ function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
62
62
$window . webkitCancelRequestAnimationFrame ||
63
63
angular . noop ;
64
64
65
- var DEGREE_IN_RADIANS = $window . Math . PI / 180 ;
66
65
var MODE_DETERMINATE = 'determinate' ;
67
66
var MODE_INDETERMINATE = 'indeterminate' ;
68
67
var DISABLED_CLASS = '_md-progress-circular-disabled' ;
@@ -103,7 +102,7 @@ function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
103
102
var path = angular . element ( node . querySelector ( 'path' ) ) ;
104
103
var startIndeterminate = $mdProgressCircular . startIndeterminate ;
105
104
var endIndeterminate = $mdProgressCircular . endIndeterminate ;
106
- var rotationIndeterminate = 0 ;
105
+ var iterationCount = 0 ;
107
106
var lastAnimationId = 0 ;
108
107
var lastDrawFrame ;
109
108
var interval ;
@@ -196,40 +195,52 @@ function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
196
195
. css ( 'transform-origin' , transformOrigin + ' ' + transformOrigin + ' ' + transformOrigin ) ;
197
196
198
197
element . css ( dimensions ) ;
199
- path . css ( 'stroke-width' , strokeWidth + 'px' ) ;
200
198
201
- renderCircle ( value , value ) ;
199
+ path . attr ( 'stroke-width' , strokeWidth ) ;
200
+ path . attr ( 'stroke-linecap' , 'square' ) ;
201
+ if ( scope . mdMode == MODE_INDETERMINATE ) {
202
+ path . attr ( 'd' , getSvgArc ( diameter , true ) ) ;
203
+ path . attr ( 'stroke-dasharray' , diameter * $window . Math . PI * 0.75 ) ;
204
+ path . attr ( 'stroke-dashoffset' , getDashLength ( diameter , 1 , 75 ) ) ;
205
+ } else {
206
+ path . attr ( 'd' , getSvgArc ( diameter , false ) ) ;
207
+ path . attr ( 'stroke-dasharray' , diameter * $window . Math . PI ) ;
208
+ path . attr ( 'stroke-dashoffset' , getDashLength ( diameter , 0 , 100 ) ) ;
209
+ renderCircle ( value , value ) ;
210
+ }
211
+
202
212
} ) ;
203
213
204
- function renderCircle ( animateFrom , animateTo , easing , duration , rotation ) {
214
+ function renderCircle ( animateFrom , animateTo , easing , duration , iterationCount , maxValue ) {
205
215
var id = ++ lastAnimationId ;
206
216
var startTime = $mdUtil . now ( ) ;
207
217
var changeInValue = animateTo - animateFrom ;
208
218
var diameter = getSize ( scope . mdDiameter ) ;
209
- var pathDiameter = diameter - getStroke ( diameter ) ;
210
219
var ease = easing || $mdProgressCircular . easeFn ;
211
220
var animationDuration = duration || $mdProgressCircular . duration ;
221
+ var rotation = - 90 * ( iterationCount || 0 ) ;
222
+ var dashLimit = maxValue || 100 ;
212
223
213
224
// No need to animate it if the values are the same
214
225
if ( animateTo === animateFrom ) {
215
- path . attr ( 'd' , getSvgArc ( animateTo , diameter , pathDiameter , rotation ) ) ;
226
+ renderFrame ( animateTo ) ;
216
227
} else {
217
228
lastDrawFrame = rAF ( function animation ( ) {
218
229
var currentTime = $window . Math . max ( 0 , $window . Math . min ( $mdUtil . now ( ) - startTime , animationDuration ) ) ;
219
230
220
- path . attr ( 'd' , getSvgArc (
221
- ease ( currentTime , animateFrom , changeInValue , animationDuration ) ,
222
- diameter ,
223
- pathDiameter ,
224
- rotation
225
- ) ) ;
231
+ renderFrame ( ease ( currentTime , animateFrom , changeInValue , animationDuration ) ) ;
226
232
227
233
// Do not allow overlapping animations
228
234
if ( id === lastAnimationId && currentTime < animationDuration ) {
229
235
lastDrawFrame = rAF ( animation ) ;
230
236
}
231
237
} ) ;
232
238
}
239
+
240
+ function renderFrame ( value ) {
241
+ path . attr ( 'stroke-dashoffset' , getDashLength ( diameter , value , dashLimit ) ) ;
242
+ path . attr ( 'transform' , 'rotate(' + ( rotation ) + ' ' + diameter / 2 + ' ' + diameter / 2 + ')' ) ;
243
+ }
233
244
}
234
245
235
246
function animateIndeterminate ( ) {
@@ -238,24 +249,22 @@ function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
238
249
endIndeterminate ,
239
250
$mdProgressCircular . easeFnIndeterminate ,
240
251
$mdProgressCircular . durationIndeterminate ,
241
- rotationIndeterminate
252
+ iterationCount ,
253
+ 75
242
254
) ;
243
255
244
- // The % 100 technically isn't necessary, but it keeps the rotation
245
- // under 100 , instead of becoming a crazy large number.
246
- rotationIndeterminate = ( rotationIndeterminate + endIndeterminate ) % 100 ;
256
+ // The %4 technically isn't necessary, but it keeps the rotation
257
+ // under 360 , instead of becoming a crazy large number.
258
+ iterationCount = ++ iterationCount % 4 ;
247
259
248
- var temp = startIndeterminate ;
249
- startIndeterminate = - endIndeterminate ;
250
- endIndeterminate = - temp ;
251
260
}
252
261
253
262
function startIndeterminateAnimation ( ) {
254
263
if ( ! interval ) {
255
264
// Note that this interval isn't supposed to trigger a digest.
256
265
interval = $interval (
257
266
animateIndeterminate ,
258
- $mdProgressCircular . durationIndeterminate + 50 ,
267
+ $mdProgressCircular . durationIndeterminate ,
259
268
0 ,
260
269
false
261
270
) ;
@@ -278,55 +287,32 @@ function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
278
287
}
279
288
280
289
/**
281
- * Generates an arc following the SVG arc syntax.
290
+ * Returns SVG path data for progress circle
282
291
* Syntax spec: https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
283
292
*
284
- * @param {number } current Current value between 0 and 100.
285
293
* @param {number } diameter Diameter of the container.
286
- * @param {number } pathDiameter Diameter of the path element.
287
- * @param {number=0 } rotation The point at which the semicircle should start rendering.
288
- * Used for doing the indeterminate animation.
294
+ * @param {boolean } indeterminate Use if progress circle will be used for indeterminate
289
295
*
290
296
* @returns {string } String representation of an SVG arc.
291
297
*/
292
- function getSvgArc ( current , diameter , pathDiameter , rotation ) {
293
- // The angle can't be exactly 360, because the arc becomes hidden.
294
- var maximumAngle = 359.99 / 100 ;
295
- var startPoint = rotation || 0 ;
298
+ function getSvgArc ( diameter , indeterminate ) {
296
299
var radius = diameter / 2 ;
297
- var pathRadius = pathDiameter / 2 ;
298
-
299
- var startAngle = startPoint * maximumAngle ;
300
- var endAngle = current * maximumAngle ;
301
- var start = polarToCartesian ( radius , pathRadius , startAngle ) ;
302
- var end = polarToCartesian ( radius , pathRadius , endAngle + startAngle ) ;
303
- var arcSweep = endAngle < 0 ? 0 : 1 ;
304
- var largeArcFlag ;
305
-
306
- if ( endAngle < 0 ) {
307
- largeArcFlag = endAngle >= - 180 ? 0 : 1 ;
308
- } else {
309
- largeArcFlag = endAngle <= 180 ? 0 : 1 ;
310
- }
311
-
312
- return 'M' + start + 'A' + pathRadius + ',' + pathRadius +
313
- ' 0 ' + largeArcFlag + ',' + arcSweep + ' ' + end ;
300
+ return 'M' + radius + ',0'
301
+ + 'A' + radius + ',' + radius + ' 0 1 1 0,' + radius // 75% circle
302
+ + ( indeterminate ? '' : 'A' + radius + ',' + radius + ' 0 0 1 ' + radius + ',0' ) ;
314
303
}
315
304
316
305
/**
317
- * Converts Polar coordinates to Cartesian.
306
+ * Return stroke length for progress circle
318
307
*
319
- * @param {number } radius Radius of the container.
320
- * @param {number } pathRadius Radius of the path element
321
- * @param {number } angleInDegress Angle at which to place the point.
308
+ * @param {number } diameter Diameter of the container.
309
+ * @param {number } value Percentage of circle (between 0 and 100)
310
+ * @param {number } limit Max percentage for circle
322
311
*
323
- * @returns {string } Cartesian coordinates in the format of `x,y`.
312
+ * @returns {number } Stroke length for progres circle
324
313
*/
325
- function polarToCartesian ( radius , pathRadius , angleInDegrees ) {
326
- var angleInRadians = ( angleInDegrees - 90 ) * DEGREE_IN_RADIANS ;
327
-
328
- return ( radius + ( pathRadius * $window . Math . cos ( angleInRadians ) ) ) +
329
- ',' + ( radius + ( pathRadius * $window . Math . sin ( angleInRadians ) ) ) ;
314
+ function getDashLength ( diameter , value , limit ) {
315
+ return diameter * $window . Math . PI * ( ( 3 * ( limit || 100 ) / 100 ) - ( value / 100 ) ) ;
330
316
}
331
317
332
318
/**
@@ -363,4 +349,5 @@ function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming,
363
349
function getStroke ( diameter ) {
364
350
return $mdProgressCircular . strokeWidth / 100 * diameter ;
365
351
}
352
+
366
353
}
0 commit comments