Skip to content

Commit

Permalink
Merge pull request #86 from setaman/optimize-loading-animation
Browse files Browse the repository at this point in the history
Optimize loading animation
  • Loading branch information
setaman authored Sep 18, 2020
2 parents aea6c85 + 0c1ad49 commit 5117047
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 33 deletions.
80 changes: 80 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 14 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@
:legendValue="1315.56"
animation="rs 2000 500"
:loading="loading"
dot="50 red"
dot="30 red"
:reverse="true"
line-mode="out"
line-mode="out 10"
:no-data="noData"
:determinate="determinate"
>
<template v-slot:default="{ counterTick }">
Expand All @@ -64,7 +65,17 @@
</template>
</vue-ellipse-progress>
</div>
<vue-ellipse-progress dot="20 green" :loading="loading" :size="200" :progress="progress" :legend-value="125.1">
<vue-ellipse-progress
dot="20 green"
:loading="loading"
:size="200"
:progress="progress"
:legend-value="125.1"
half
line-mode="out 20"
:no-data="noData"
:determinate="determinate"
>
<template v-slot:legend-caption>
<p slot="legend-caption">TASKS DONE</p>
</template>
Expand Down
15 changes: 10 additions & 5 deletions src/components/Circle/Circle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
:fill="computedEmptyColorFill"
:class="{ 'ep-circle--nodata': !dataIsAvailable }"
:style="{
transitionDuration: styles.transitionDuration,
transitionDuration: animationDuration,
transitionTimingFunction: styles.transitionTimingFunction,
}"
:stroke-width="computedEmptyThickness"
>
</circle>
<fade-in-transition>
<g v-if="showDeterminate">
<g style="opacity: 0.45;">
<g v-if="isLoading">
<g class="ep-circle--loading__container" :style="{ opacity: `${loading ? 1 : 0.45}` }">
<circle
class="ep-circle--determinate animation__loading"
class="ep-circle--loading animation__loading"
:r="radius"
:cx="position"
:cy="position"
Expand All @@ -36,7 +36,12 @@
:stroke-width="computedThickness"
:stroke-linecap="line"
:stroke-dasharray="circumference"
:style="styles"
:style="{
transitionTimingFunction: styles.transitionTimingFunction,
transformOrigin: styles.transformOrigin,
'--ep-loading-stroke-offset': styles['--ep-loading-stroke-offset'],
'--ep-circumference': styles['--ep-circumference'],
}"
>
</circle>
</g>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Circle/CircleDot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default {
width: `${this.dotContainerSize}px`,
height: `${this.dotContainerSize}px`,
transform: `rotate(${this.dotContainerRotation}deg)`,
transitionDuration: this.loading ? "0s" : this.animationDuration,
transitionDuration: this.loading || !this.dataIsAvailable ? "0s" : this.animationDuration,
transitionTimingFunction: "ease-in-out",
"animation-duration": this.animationDuration,
"--ep-dot-start": `${this.dotStart}deg`,
Expand Down Expand Up @@ -63,7 +63,7 @@ export default {
width: `${this.dotSize}px`,
backgroundColor: this.dotColor,
...this.dot,
transitionDuration: this.loading ? "0s" : this.animationDuration,
transitionDuration: this.loading || !this.dataIsAvailable ? "0s" : this.animationDuration,
height: `${this.dotSize}px`,
};
},
Expand Down
16 changes: 11 additions & 5 deletions src/components/Circle/HalfCircle.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,30 @@
:stroke-linecap="line"
:stroke-dasharray="emptyDasharray"
:style="{
transitionDuration: styles.transitionDuration,
transitionDuration: animationDuration,
transitionTimingFunction: styles.transitionTimingFunction,
}"
:class="{ 'ep-circle--nodata': !dataIsAvailable }"
>
</path>
<fade-in-transition>
<g v-if="showDeterminate">
<g style="opacity: 0.6;">
<g v-if="isLoading">
<g :style="{ opacity: `${loading ? 1 : 0.45}` }">
<path
:stroke-width="computedThickness"
class="ep-half-circle--determinate animation__loading"
class="ep-half-circle--loading animation__loading"
:d="path"
:fill="computedColorFill"
:stroke="computedColor"
:stroke-dasharray="circumference"
:stroke-linecap="line"
:style="styles"
:style="{
transitionTimingFunction: styles.transitionTimingFunction,
transformOrigin: styles.transformOrigin,
'--ep-loading-stroke-offset': styles['--ep-loading-stroke-offset'],
'--ep-circumference': styles['--ep-circumference'],
'--ep-negative-circumference': styles['--ep-negative-circumference'],
}"
>
</path>
</g>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Circle/circleMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ export default {
`animation__${
!this.loading && this.dataIsAvailable && this.isInitialized ? this.parsedAnimation.type : "none"
}`,
`${this.loading ? "animation__loading" : ""}`,
];
},
animationDuration() {
Expand Down Expand Up @@ -235,10 +234,11 @@ export default {

styles() {
return {
transition: `${this.animationDuration}, opacity 0.3s`,
strokeDashoffset: this.strokeDashOffset,
transitionDuration: this.animationDuration,
transitionTimingFunction: "ease-in-out",
transformOrigin: this.transformOrigin,
opacity: this.loading || !this.dataIsAvailable ? 0 : 1,
"--ep-circumference": this.circumference,
"--ep-negative-circumference": this.getNegativeCircumference(),
"--ep-double-circumference": this.getDoubleCircumference(),
Expand All @@ -252,8 +252,8 @@ export default {
};
},

showDeterminate() {
return this.determinate && !this.loading && this.dataIsAvailable;
isLoading() {
return (this.determinate || this.loading) && this.dataIsAvailable;
},
},
methods: {
Expand Down
19 changes: 18 additions & 1 deletion src/styles/animations.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}
}

@mixin ep-half-progress--loading ($offset, $circumference, $double_circumference) {
/*@mixin ep-half-progress--loading ($circumference, $double_circumference) {
@keyframes ep-half-progress--loading {
0% {
opacity: 0.5;
Expand All @@ -38,6 +38,23 @@
stroke-dashoffset: $circumference;
}
}
}*/

@mixin ep-half-progress--loading ($circumference) {
@keyframes ep-half-progress--loading {
0% {
opacity: 0.5;
stroke-dashoffset: $circumference;
}
50% {
opacity: 0.8;
stroke-dashoffset: 0;
}
100% {
opacity: 0.5;
stroke-dashoffset: $circumference;
}
}
}

@mixin ep-progress--loading__rotation {
Expand Down
7 changes: 3 additions & 4 deletions src/styles/animationsUsage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
}
}

.ep-circle--progress, .ep-circle--determinate {
.ep-circle--loading {
&.animation__loading {
animation-name: ep-progress--loading, ep-progress--loading__rotation;
animation-iteration-count: infinite !important;
Expand All @@ -26,7 +26,7 @@
}
}

.ep-half-circle--progress, .ep-half-circle--determinate {
.ep-half-circle--loading {
&.animation__loading {
animation-name: ep-half-progress--loading;
animation-iteration-count: infinite !important;
Expand Down Expand Up @@ -87,7 +87,6 @@
var(--ep-negative-circumference)
);
@include ep-progress--loading(var(--ep-loading-stroke-offset), var(--ep-circumference));
@include ep-half-progress--loading(var(--ep-loading-stroke-offset), var(--ep-circumference),
var(--ep-negative-circumference));
@include ep-half-progress--loading(var(--ep-circumference));
@include ep-progress--loading__rotation();
@include ep-dot--init__rs(var(--ep-dot-start), var(--ep-dot-end), var(--ep-dot-360));
6 changes: 3 additions & 3 deletions tests/unit/circle/circle-animation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@ const animationDurationTests = (container, circleClass, prefix = "circle | ") =>
it(`${prefix} applies default @1000 duration value as transition and animation duration`, () => {
const circleProgressWrapper = factory({}, container).find(circleClass);

expect(circleProgressWrapper.element.style.transitionDuration).to.equal("1000ms");
expect(circleProgressWrapper.element.style.transition).to.include("1000ms");
expect(circleProgressWrapper.element.style.animationDuration).to.equal("1000ms");
});
it(`${prefix} applies provided duration value as transition and animation duration`, () => {
const circleProgressWrapper = factory({ animation: "rs 500" }, container).find(circleClass);

expect(circleProgressWrapper.element.style.transitionDuration).to.equal("500ms");
expect(circleProgressWrapper.element.style.transition).to.include("500ms");
expect(circleProgressWrapper.element.style.animationDuration).to.equal("500ms");
});
it(`${prefix} applies @0 duration value as transition and animation duration`, () => {
const circleProgressWrapper = factory({ animation: "rs 0" }, container).find(circleClass);

expect(circleProgressWrapper.element.style.transitionDuration).to.equal("0ms");
expect(circleProgressWrapper.element.style.transition).to.include("0ms");
expect(circleProgressWrapper.element.style.animationDuration).to.equal("0ms");
});
};
Expand Down
26 changes: 20 additions & 6 deletions tests/unit/circle/circle.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ describe("[ CircleProgress.vue | HalfCircleProgress.vue ]", () => {
it("resets the progress circle animation class", () => {
expect(circleProgressWrapper.classes()).to.not.include("animation__default");
});
it("applies 0 opacity to progress circle", () => {
expect(circleProgressWrapper.element.style.opacity).to.equal("0");
});
});
describe("#loading", () => {
const progress = 60;
Expand All @@ -208,8 +211,15 @@ describe("[ CircleProgress.vue | HalfCircleProgress.vue ]", () => {

expect(circleProgressWrapper.element.style.strokeDashoffset).to.equal(`${circumference}`);
});
it("adds .animation__loading class to progress circle", () => {
expect(circleProgressWrapper.classes()).to.include("animation__loading");
it("applies 0 opacity to progress circle", () => {
expect(circleProgressWrapper.element.style.opacity).to.equal("0");
});
it("applies 1 opacity to loading circle container", () => {
const determinateCircleWrapper = wrapper.find(".ep-circle--loading__container");
expect(determinateCircleWrapper.element.style.opacity).to.equal("1");
});
it("renders the loading circle", () => {
expect(wrapper.find(".ep-circle--loading").exists()).to.be.true;
});
});
describe("#determinate", () => {
Expand All @@ -223,15 +233,19 @@ describe("[ CircleProgress.vue | HalfCircleProgress.vue ]", () => {
determinate: true,
});

it("shows the determinate loading circle", () => {
expect(wrapper.find(".ep-circle--determinate").exists()).to.be.true;
it("shows the loading circle", () => {
expect(wrapper.find(".animation__loading").exists()).to.be.true;
});
it("applies same styles to determinate circle as to progress circle", () => {
const determinateCircleWrapper = wrapper.find(".ep-circle--determinate");
it("applies same styles to loading circle as to progress circle", () => {
const determinateCircleWrapper = wrapper.find(".animation__loading");
expect(determinateCircleWrapper.element.getAttribute("stroke")).to.equal(`${color}`);
expect(determinateCircleWrapper.element.getAttribute("stroke-width")).to.equal(`${thickness}`);
expect(determinateCircleWrapper.element.getAttribute("fill")).to.equal("transparent");
});
it("applies 0.45 opacity to loading circle container", () => {
const determinateCircleWrapper = wrapper.find(".ep-circle--loading__container");
expect(determinateCircleWrapper.element.style.opacity).to.equal("0.45");
});
});
describe("#angle", () => {
const circleWrapper = factory({ progress: 50 });
Expand Down

0 comments on commit 5117047

Please sign in to comment.