1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-21 21:33:18 +01:00
Files
dozzle/assets/components/ScrollProgress.vue
Amir Raminfar 412a10256d Vue3 (#1594)
* WIP vue3

* WIP vue3

* WIP vue3

* Migrates to vitejs

* Fixes js tests and removes not needed modules

* Fixes unmount

* Updates to use css instead for space

* Fixes tests and rebases one more time

* Uses orgua

* Fixes migrations bugs with oruga and fixes scroll

* Fixes v-deep

* Fixes icons to prod

* Fixes icons to prod

* Adds favicon back

* Transitions some to composition api

* Updates another component to comp api

* Cleans defineProps

* Updates log messages

* Moves more to compose api

* Cleans up styles and rewrites event source

* Tries to fix DOMPurify

* Removes postcss

* WIP typescript

* Improves importing

* Converts all to ts

* Converts main to ts

* Makes changes for tsconfig

* Moves more to ts

* Adds typing to store

* More typing

* Updates to ts

* Updates the rest to ts

* Fixes computes

* Fixes unmount

* Adds cypress with custom base fixed

* Fixes jest tests

* Fixes golang tests

* Adds gitignore for cypress

* Removes int in favor of e2e with cypress

* Tries to fix int tests again

* Adds title

* Updates e2e tests

* Uses vue for isMobile

* Removes app spec

* Cleans up docker

* Adds drop down for settings

* Fixes bug with restart

* Fixes scroll up bug

* Adds tests for light mode
2021-11-16 10:55:44 -08:00

150 lines
3.5 KiB
Vue

<template>
<div class="scroll-progress">
<svg width="100" height="100" viewBox="0 0 100 100" :class="{ indeterminate }">
<circle r="44" cx="50" cy="50" :style="{ '--progress': scrollProgress }" />
</svg>
<div class="is-overlay columns is-vcentered is-centered has-text-weight-light">
<template v-if="indeterminate">
<div class="column is-narrow is-paddingless is-size-2">&#8734;</div>
</template>
<template v-else>
<span class="column is-narrow is-paddingless is-size-2">
{{ Math.ceil(scrollProgress * 100) }}
</span>
<span class="column is-narrow is-paddingless"> % </span>
</template>
</div>
</div>
</template>
<script lang="ts">
import { mapGetters } from "vuex";
import throttle from "lodash.throttle";
export default {
name: "ScrollProgress",
props: {
indeterminate: {
default: false,
type: Boolean,
},
autoHide: {
default: true,
type: Boolean,
},
},
data() {
return {
scrollProgress: 0,
animation: { cancel: () => {} },
parentElement: document,
};
},
created() {
this.onScrollThrottled = throttle(this.onScroll, 150);
},
mounted() {
this.attachEvents();
},
beforeUnmount() {
this.detachEvents();
},
watch: {
activeContainers() {
this.detachEvents();
this.attachEvents();
},
indeterminate() {
this.$nextTick(() => this.onScroll());
},
},
computed: {
...mapGetters(["activeContainers"]),
},
methods: {
attachEvents() {
this.parentElement = this.$el.closest("[data-scrolling]") || document;
this.parentElement.addEventListener("scroll", this.onScrollThrottled);
},
detachEvents() {
this.parentElement.removeEventListener("scroll", this.onScrollThrottled);
},
onScroll() {
const p = this.parentElement == document ? document.documentElement : this.parentElement;
this.scrollProgress = p.scrollTop / (p.scrollHeight - p.clientHeight);
this.animation.cancel();
if (this.autoHide) {
this.animation = this.$el.animate(
{ opacity: [1, 0] },
{
duration: 500,
delay: 2000,
fill: "both",
easing: "ease-out",
}
);
}
},
},
};
</script>
<style scoped lang="scss">
.scroll-progress {
display: inline-block;
position: relative;
pointer-events: none;
svg {
filter: drop-shadow(0px 1px 1px rgba(0, 0, 0, 0.2));
margin-top: 5px;
&.indeterminate {
animation: 2s linear infinite svg-animation;
circle {
animation: 1.4s ease-in-out infinite both circle-animation;
}
}
circle {
fill: var(--scheme-main-ter);
fill-opacity: 0.8;
transition: stroke-dashoffset 250ms ease-out;
transform: rotate(-90deg);
transform-origin: 50% 50%;
stroke: var(--primary-color);
stroke-dashoffset: calc(276.32px - var(--progress) * 276.32px);
stroke-dasharray: 276.32px 276.32px;
stroke-linecap: round;
stroke-width: 3;
will-change: stroke-dashoffset;
}
}
}
@keyframes svg-animation {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
@keyframes circle-animation {
0%,
25% {
stroke-dashoffset: 275px;
transform: rotate(0);
}
50%,
75% {
stroke-dashoffset: 70px;
transform: rotate(45deg);
}
100% {
stroke-dashoffset: 275px;
transform: rotate(360deg);
}
}
</style>