Skip to content

Commit

Permalink
feat(katzencore): Added Scroll Animations to composables
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximilian Schleining committed Aug 12, 2024
1 parent 5732cf1 commit 3ee8fbc
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 24 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Edit content directly in your Nuxt App, store your content in an [Unstorage](htt
and deploy your content to the Edge or host it on your server.

### Warning
**In active development, not ready for production use.**
**In active development, bugs may be present**

_Feel free to contribute to this project by creating a pull request.🐱❤️_

Expand Down
45 changes: 45 additions & 0 deletions playground/pages/animation_test.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script setup lang="ts">
const section1 = ref<HTMLElement | null>(null)
const animation = useScrollAnimation({element:section1})
const globalScroll = useScrollAnimation({global: true})
const screenScroll = useScrollAnimation({screenHeight: true})
</script>

<template>
<div>
<h1>Animation Test Page</h1>
<div class="flex flex-col">
<div class="flex flex-row">
<p>On this page the useAnimation Composables are tested</p>
</div>
</div>


<div class="fixed top-0 left-0 font-bold text-2xl text-black bg-white p-4 border border-black rounded-lg">
<span>GlobalScroll: {{globalScroll}}</span>

<br>

<span>ScreenScroll: {{screenScroll}}</span>

</div>

<div class="h-screen w-full bg-gray-100 flex flex-col items-center justify-between" ref="section1">
<h2>SECTION 1</h2>
<p>{{animation}}</p>
</div>
<div class="h-screen w-full bg-red-100 flex flex-col items-center justify-center">
<h2>SECTION 2</h2>
</div>

<div class="h-screen w-full bg-red-100 flex flex-col items-center justify-center">
<h2>SECTION 3</h2>
</div>
</div>
</template>

<style scoped>
</style>
23 changes: 0 additions & 23 deletions playground/pages/test_page.vue

This file was deleted.

72 changes: 72 additions & 0 deletions src/runtime/composables/useAnimation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
*
* Katze Animation Library
* - useScrollAnimation
* - useTimelineAnimation (WIP)
*/
import { ref, watch } from 'vue'
import type { Ref } from 'vue'
import { onMounted, onUnmounted } from '#imports'

interface ScrollAnimationOptions {
global?: boolean
screenHeight?: boolean
element?: Ref<HTMLElement | null>
}

interface UpdateFunction {
(values: ScrollAnimationValues): void
}

interface ScrollAnimationValues {
capped: number
full: number
}

const watchingElements: Map<HTMLElement, UpdateFunction> = new Map()
const globalScrollPercentage = ref<ScrollAnimationValues>({ capped: 0, full: 0 })
const screenHeightPercentage = ref<ScrollAnimationValues>({ capped: 0, full: 0 })

export const useScrollAnimation = (options: ScrollAnimationOptions) => {
let reactiveScrollProperty = ref<ScrollAnimationValues>({ capped: 0, full: 0 })
if (options.global) {
reactiveScrollProperty = globalScrollPercentage
}
else if (options.screenHeight) {
reactiveScrollProperty = screenHeightPercentage
}
else if (options.element) {
// wait for element to be mounted
onMounted(() => {
const updateFunction = (values: ScrollAnimationValues) => {
reactiveScrollProperty.value = values
}
watchingElements.set(<HTMLElement>options.element?.value, updateFunction)
})
}
else {
throw new Error('Please provide an element or set global or screenHeight to true in the options')
}

onMounted(() => window.addEventListener('scroll', globalScrollListener))
onUnmounted(() => window.removeEventListener('scroll', globalScrollListener))

return reactiveScrollProperty
}

const globalScrollListener = () => {
const scrollY = window.scrollY

const globalPercent = scrollY / (document.body.scrollHeight - window.innerHeight)
globalScrollPercentage.value = { capped: Math.min(1, globalPercent), full: globalPercent }

const screenHeightPercent = scrollY / window.innerHeight
screenHeightPercentage.value = { capped: Math.min(1, screenHeightPercent), full: screenHeightPercent }

watchingElements.forEach((updateFunction, element) => {
const elementTop = element.getBoundingClientRect().top
const elementHeight = element.getBoundingClientRect().height
const cappedValue = Math.max(0, Math.min(1, (elementTop + elementHeight) / window.innerHeight))
updateFunction({ capped: 1 - cappedValue, full: (-1 * (elementTop / window.innerHeight)) })
})
}

0 comments on commit 3ee8fbc

Please sign in to comment.