This repository has been archived by the owner on Sep 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(circular_progress): Add circular progress component
This commit adds a new component, material-circular-progress, which enables the use of both determinate and indeterminate circular progress indicators. Fixes Issue #192 Closes #365
- Loading branch information
1 parent
5847006
commit 07d5653
Showing
10 changed files
with
315 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Circular progress indicators, created with the `<material-circular-progress>` directive. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
$circle-size:48px; | ||
$circle-background:transparent; | ||
$circle-color:$color-blue-500; | ||
$inset-size:36px; | ||
$inset-color:white; | ||
$transition-length:.3s; | ||
$shadow:6px 6px 10px rgba(0, 0, 0, 0.2); | ||
material-circular-progress { | ||
display: block; | ||
width: $circle-size + 6; | ||
height: $circle-size + 6; | ||
background-color: $circle-background; | ||
border-radius: 50%; | ||
padding: 3px; | ||
|
||
.wrapper1, .wrapper2 { | ||
width: $circle-size; | ||
height: $circle-size; | ||
position: absolute; | ||
border-radius: 50%; | ||
} | ||
|
||
.circle { | ||
.mask, .fill, .shadow { | ||
width: $circle-size; | ||
height: $circle-size; | ||
position: absolute; | ||
border-radius: 50%; | ||
} | ||
|
||
.shadow { } | ||
|
||
.mask, .fill { | ||
-webkit-backface-visibility: hidden; | ||
transition: -webkit-transform $transition-length; | ||
transition: -ms-transform $transition-length; | ||
transition: transform $transition-length; | ||
} | ||
|
||
.mask { | ||
clip: rect(0px, $circle-size, $circle-size, $circle-size/2); | ||
.fill { | ||
clip: rect(0px, $circle-size/2, $circle-size, 0px); | ||
background-color: $circle-color; | ||
} | ||
} | ||
} | ||
|
||
.inset { | ||
width: $inset-size; | ||
height: $inset-size; | ||
position: absolute; | ||
margin-left: ($circle-size - $inset-size)/2; | ||
margin-top: ($circle-size - $inset-size)/2; | ||
background-color: $inset-color; | ||
border-radius: 50%; | ||
} | ||
|
||
&[mode=indeterminate] { | ||
.wrapper1, .wrapper2 { | ||
-ms-transform-origin: 50% 50%; /* IE 9 */ | ||
webkit-transform-origin: 50% 50%; /* Chrome, Safari, Opera */ | ||
transform-origin: 50% 50%; | ||
} | ||
|
||
.wrapper1{ | ||
@include animation(indeterminate_rotate1 3s infinite linear); | ||
} | ||
|
||
.wrapper2{ | ||
@include animation(indeterminate_rotate2 1.5s infinite linear); | ||
} | ||
|
||
.fill, .mask.full{ | ||
@include animation(indeterminate_size_fill 1.5s infinite linear); | ||
} | ||
|
||
.fill.fix { | ||
@include animation(indeterminate_size_fix 1.5s infinite linear); | ||
} | ||
} | ||
} | ||
|
||
@include keyframes(indeterminate_rotate1) { | ||
0%{ | ||
@include transform(rotate(0deg)); | ||
} | ||
100%{ | ||
@include transform(rotate(360deg)); | ||
} | ||
} | ||
|
||
@include keyframes(indeterminate_rotate2) { | ||
0%{ | ||
@include transform(rotate(0deg)); | ||
} | ||
70%{ | ||
@include transform(rotate(0deg)); | ||
} | ||
100%{ | ||
@include transform(rotate(360deg)); | ||
} | ||
} | ||
|
||
@include keyframes(indeterminate_size_fill) { | ||
0%{ | ||
@include transform(rotate(5deg)); | ||
} | ||
10%{ | ||
@include transform(rotate(5deg)); | ||
} | ||
50%{ | ||
@include transform(rotate(135deg)); | ||
} | ||
70%{ | ||
@include transform(rotate(135deg)); | ||
} | ||
100%{ | ||
@include transform(rotate(5deg)); | ||
} | ||
} | ||
|
||
@include keyframes(indeterminate_size_fix) { | ||
0%{ | ||
@include transform(rotate(10deg)); | ||
} | ||
10%{ | ||
@include transform(rotate(10deg)); | ||
} | ||
50%{ | ||
@include transform(rotate(270deg)); | ||
} | ||
70%{ | ||
@include transform(rotate(270deg)); | ||
} | ||
100%{ | ||
@include transform(rotate(10deg)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/** | ||
* @ngdoc module | ||
* @name material.components.circularProgress | ||
* @description Circular Progress module! | ||
*/ | ||
angular.module('material.components.circularProgress', [ | ||
'material.animations', | ||
'material.services.aria' | ||
]) | ||
.directive('materialCircularProgress', [ | ||
'$$rAF', | ||
'$materialEffects', | ||
MaterialCircularProgressDirective | ||
]); | ||
|
||
/** | ||
* @ngdoc directive | ||
* @name materialCircularProgress | ||
* @module material.components.circularProgress | ||
* @restrict E | ||
* | ||
* @description | ||
* The circular progress directive is used to make loading content in your app as delightful and painless as possible by minimizing the amount of visual change a user sees before they can view and interact with content. | ||
* | ||
* For operations where the percentage of the operation completed can be determined, use a determinate indicator. They give users a quick sense of how long an operation will take. | ||
* | ||
* For operations where the user is asked to wait a moment while something finishes up, and it’s not necessary to expose what's happening behind the scenes and how long it will take, use an indeterminate indicator. | ||
* | ||
* @param {string} mode Select from one of two modes: determinate and indeterminate. | ||
* @param {number=} value In determinate mode, this number represents the percentage of the circular progress. Default: 0 | ||
* @param {number=} diameter This specifies the diamter of the circular progress. Default: 48 | ||
* | ||
* @usage | ||
* <hljs lang="html"> | ||
* <material-circular-progress mode="determinate" value="..."></material-circular-progress> | ||
* | ||
* <material-circular-progress mode="determinate" ng-value="..."></material-circular-progress> | ||
* | ||
* <material-circular-progress mode="determinate" value="..." diameter="100"></material-circular-progress> | ||
* | ||
* <material-circular-progress mode="indeterminate"></material-circular-progress> | ||
* </hljs> | ||
*/ | ||
function MaterialCircularProgressDirective($$rAF, $materialEffects) { | ||
var fillRotations = new Array(101), | ||
fixRotations = new Array(101); | ||
|
||
for (var i = 0; i < 101; i++) { | ||
var percent = i / 100; | ||
var rotation = Math.floor(percent * 180); | ||
|
||
fillRotations[i] = 'rotate(' + rotation.toString() + 'deg)'; | ||
fixRotations[i] = 'rotate(' + (rotation * 2).toString() + 'deg)'; | ||
} | ||
|
||
return { | ||
restrict: 'E', | ||
template: | ||
'<div class="wrapper1"><div class="wrapper2"><div class="circle">' + | ||
'<div class="mask full">' + | ||
'<div class="fill"></div>' + | ||
'</div>' + | ||
'<div class="mask half">' + | ||
'<div class="fill"></div>' + | ||
'<div class="fill fix"></div>' + | ||
'</div>' + | ||
'<div class="shadow"></div>' + | ||
'</div>' + | ||
'<div class="inset"></div></div></div>', | ||
compile: compile | ||
}; | ||
|
||
function compile(tElement, tAttrs, transclude) { | ||
tElement.attr('aria-valuemin', 0); | ||
tElement.attr('aria-valuemax', 100); | ||
tElement.attr('role', 'progressbar'); | ||
|
||
return postLink; | ||
} | ||
|
||
function postLink(scope, element, attr) { | ||
var circle = element[0], | ||
fill = circle.querySelectorAll('.fill, .mask.full'), | ||
fix = circle.querySelectorAll('.fill.fix'), | ||
i, clamped, fillRotation, fixRotation; | ||
|
||
var diameter = attr.diameter || 48; | ||
var scale = diameter/48; | ||
|
||
circle.style[$materialEffects.TRANSFORM] = 'scale(' + scale.toString() + ')'; | ||
|
||
attr.$observe('value', function(value) { | ||
clamped = clamp(value); | ||
fillRotation = fillRotations[clamped]; | ||
fixRotation = fixRotations[clamped]; | ||
|
||
element.attr('aria-valuenow', clamped); | ||
|
||
for (i = 0; i < fill.length; i++) { | ||
fill[i].style[$materialEffects.TRANSFORM] = fillRotation; | ||
} | ||
|
||
for (i = 0; i < fix.length; i++) { | ||
fix[i].style[$materialEffects.TRANSFORM] = fixRotation; | ||
} | ||
}); | ||
} | ||
|
||
function clamp(value) { | ||
if (value > 100) { | ||
return 100; | ||
} | ||
|
||
if (value < 0) { | ||
return 0; | ||
} | ||
|
||
return Math.ceil(value || 0); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
describe('materialCircularProgress', function() { | ||
beforeEach(module('material.components.circularProgress')); | ||
|
||
it('should update aria-valuenow', inject(function($compile, $rootScope) { | ||
var element = $compile('<div>' + | ||
'<material-circular-progress value="{{progress}}">' + | ||
'</material-circular-progress>' + | ||
'</div>')($rootScope); | ||
|
||
$rootScope.$apply(function() { | ||
$rootScope.progress = 50; | ||
}); | ||
|
||
var progress = element.find('material-circular-progress'); | ||
|
||
expect(progress.eq(0).attr('aria-valuenow')).toEqual('50'); | ||
})); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<div ng-controller="AppCtrl" layout="vertical" layout-padding> | ||
<h3>Determinate</h3> | ||
<material-circular-progress mode="determinate" value="{{determinateValue}}"></material-circular-progress> | ||
|
||
<h3>Indeterminate</h3> | ||
<material-circular-progress mode="indeterminate"></material-circular-progress> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
angular.module('circularProgressDemo1', ['ngMaterial']) | ||
.controller('AppCtrl', ['$scope', '$interval', | ||
function($scope, $interval) { | ||
$scope.mode = 'query'; | ||
$scope.determinateValue = 30; | ||
|
||
$interval(function() { | ||
$scope.determinateValue += 1; | ||
if ($scope.determinateValue > 100) { | ||
$scope.determinateValue = 30; | ||
} | ||
}, 100, 0, true); | ||
} | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
body { | ||
padding: 20px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"module": "material.components.circularProgress", | ||
"name": "Circular Progress", | ||
"demos": { | ||
"demo1": { | ||
"name": "Circular Progress Basic Usage", | ||
"files": ["demo1/*"] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters