frontend performance improvements #59
2 changed files with 45 additions and 13 deletions
|
@ -23,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onMounted, onUnmounted, shallowRef } from 'vue';
|
import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { calcPopupPosition } from '@/scripts/popup-position.js';
|
import { calcPopupPosition } from '@/scripts/popup-position.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
|
@ -70,7 +70,7 @@ function setPosition() {
|
||||||
el.value.style.top = data.top + 'px';
|
el.value.style.top = data.top + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
let loopHandler;
|
let loopHandler: number | undefined;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
@ -81,12 +81,23 @@ onMounted(() => {
|
||||||
loopHandler = window.requestAnimationFrame(loop);
|
loopHandler = window.requestAnimationFrame(loop);
|
||||||
};
|
};
|
||||||
|
|
||||||
loop();
|
watch(() => props.showing, show => {
|
||||||
|
if (show) {
|
||||||
|
if (!loopHandler) {
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
} else if (loopHandler) {
|
||||||
|
window.cancelAnimationFrame(loopHandler);
|
||||||
|
loopHandler = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.cancelAnimationFrame(loopHandler);
|
if (loopHandler) {
|
||||||
|
window.cancelAnimationFrame(loopHandler);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
import MkOmit from '@/components/MkOmit.vue';
|
import MkOmit from '@/components/MkOmit.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { getScrollPosition } from '@/scripts/scroll.js';
|
import { getScrollContainer } from '@/scripts/scroll.js';
|
||||||
import { getUserMenu } from '@/scripts/get-user-menu.js';
|
import { getUserMenu } from '@/scripts/get-user-menu.js';
|
||||||
import number from '@/filters/number.js';
|
import number from '@/filters/number.js';
|
||||||
import { userPage } from '@/filters/user.js';
|
import { userPage } from '@/filters/user.js';
|
||||||
|
@ -282,6 +282,7 @@ const isEditingMemo = ref(false);
|
||||||
const moderationNote = ref(props.user.moderationNote);
|
const moderationNote = ref(props.user.moderationNote);
|
||||||
const editModerationNote = ref(false);
|
const editModerationNote = ref(false);
|
||||||
const movedFromLog = ref<null | {movedFromId:string;}[]>(null);
|
const movedFromLog = ref<null | {movedFromId:string;}[]>(null);
|
||||||
|
let scrollEl: null | HTMLElement = null;
|
||||||
|
|
||||||
watch(moderationNote, async () => {
|
watch(moderationNote, async () => {
|
||||||
await misskeyApi('admin/update-user-note', { userId: props.user.id, text: moderationNote.value });
|
await misskeyApi('admin/update-user-note', { userId: props.user.id, text: moderationNote.value });
|
||||||
|
@ -313,15 +314,19 @@ async function fetchMovedFromLog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parallaxLoop() {
|
function parallaxLoop() {
|
||||||
parallaxAnimationId.value = window.requestAnimationFrame(parallaxLoop);
|
requestNextParallaxFrame();
|
||||||
parallax();
|
parallax();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function requestNextParallaxFrame() {
|
||||||
|
parallaxAnimationId.value = window.requestAnimationFrame(parallaxLoop);
|
||||||
|
}
|
||||||
|
|
||||||
function parallax() {
|
function parallax() {
|
||||||
const banner = bannerEl.value as any;
|
const banner = bannerEl.value as any;
|
||||||
if (banner == null) return;
|
if (banner == null) return;
|
||||||
|
|
||||||
const top = getScrollPosition(rootEl.value);
|
const top = scrollEl?.scrollTop ?? scrollY;
|
||||||
|
|
||||||
if (top < 0) return;
|
if (top < 0) return;
|
||||||
|
|
||||||
|
@ -330,6 +335,23 @@ function parallax() {
|
||||||
banner.style.backgroundPosition = `center calc(50% - ${pos}px)`;
|
banner.style.backgroundPosition = `center calc(50% - ${pos}px)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startParallax() {
|
||||||
|
(scrollEl ?? window).removeEventListener('scroll', startParallax);
|
||||||
|
requestNextParallaxFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addScrollEvent() {
|
||||||
|
(scrollEl ?? window).addEventListener('scroll', startParallax);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelParallax() {
|
||||||
|
if (parallaxAnimationId.value) {
|
||||||
|
window.cancelAnimationFrame(parallaxAnimationId.value);
|
||||||
|
parallaxAnimationId.value = null;
|
||||||
|
addScrollEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showMemoTextarea() {
|
function showMemoTextarea() {
|
||||||
isEditingMemo.value = true;
|
isEditingMemo.value = true;
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
@ -394,7 +416,10 @@ watch([props.user], () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window.requestAnimationFrame(parallaxLoop);
|
scrollEl = getScrollContainer(rootEl.value);
|
||||||
|
addScrollEvent();
|
||||||
|
(scrollEl ?? window).addEventListener('scrollend', cancelParallax);
|
||||||
|
parallax();
|
||||||
narrow.value = rootEl.value!.clientWidth < 1000;
|
narrow.value = rootEl.value!.clientWidth < 1000;
|
||||||
|
|
||||||
if (props.user.birthday) {
|
if (props.user.birthday) {
|
||||||
|
@ -417,11 +442,7 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(cancelParallax);
|
||||||
if (parallaxAnimationId.value) {
|
|
||||||
window.cancelAnimationFrame(parallaxAnimationId.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
Loading…
Reference in a new issue