Skip to content

Commit

Permalink
Logo ticker updates and carousel buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
Lindsey Zylstra committed Nov 14, 2024
1 parent 9ed79fc commit c2552ff
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 216 deletions.
2 changes: 1 addition & 1 deletion components/Block/Carousel/Carousel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ onMounted(async () => {
display: flex;
justify-content: center;
gap: 60px;
margin-top: 40px;
margin-top: 65px;
}
&__button {
Expand Down
115 changes: 15 additions & 100 deletions components/LogoDoubleTicker.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<script setup lang="ts">
import { useIntersectionObserver, useResizeObserver } from '@vueuse/core';
import type { BlockLogoCloudLogo } from '~/types/schema/blocks';
import type { File } from '~/types/schema';
import { Vue3Marquee } from 'vue3-marquee';
const props = defineProps<{
logos: BlockLogoCloudLogo[];
Expand All @@ -20,131 +19,47 @@ const bottomLogoArray = computed(() => {
const blockLogos = unref(props.logos) ?? [];
return blockLogos.slice(halfLength);
});
const ticker = ref<HTMLElement | null>(null);
const target = ref<HTMLElement | null>(null);
const tickerWidth = ref<number | null>(null);
const isVisible = ref(false);
useIntersectionObserver(
target,
([{ isIntersecting }]) => {
isVisible.value = isIntersecting;
},
{
threshold: 0.25,
},
);
const duration = computed(() => {
if (tickerWidth.value) {
const calculatedDuration = tickerWidth.value / 60; // 60px per second;
return `${calculatedDuration * 1000}ms`;
} else return '0ms';
});
// Adjust duration on resize
useResizeObserver(ticker, (entries) => {
tickerWidth.value = (entries[0].target as HTMLElement).offsetWidth;
});
</script>

<template>
<div class="block-logocloud-ticker">
<div ref="target" class="marquee-wrapper">
<div
ref="ticker"
:class="[{ animate: isVisible }, 'marquee']"
:style="{
'--marquee-duration': duration,
}"
>
<Vue3Marquee :clone="true" :gradient="true" :gradient-color="[250, 250, 250]" gradient-length="5%">
<div class="logo-container">
<BaseDirectusImage
v-for="logo in topLogoArray"
:key="logo.id"
:uuid="(logo.directus_files_id as File).id"
:alt="(logo.directus_files_id as File).description ?? ''"
/>
<div class="logo-spacer"></div>
</div>
</div>
</div>
<div class="block-logocloud-ticker">
<div ref="target" class="marquee-wrapper">
<div
ref="ticker"
:class="[{ animate: isVisible }, 'marquee reverse-marquee']"
:style="{
'--marquee-duration': duration,
}"
>
</Vue3Marquee>
<Vue3Marquee :gradient="true" :gradient-color="[250, 250, 250]" gradient-length="5%" direction="reverse">
<div class="logo-container">
<BaseDirectusImage
v-for="logo in bottomLogoArray"
:key="logo.id"
:uuid="(logo.directus_files_id as File).id"
:alt="(logo.directus_files_id as File).description ?? ''"
/>
<div class="logo-spacer"></div>
</div>
</div>
</Vue3Marquee>
</div>
</template>
<style scoped lang="scss">
.block-logocloud-ticker {
position: relative;
display: flex;
overflow: hidden;
.marquee-wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100"><defs><linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="white" stop-opacity="0"/><stop offset="20%" stop-color="white"/><stop offset="80%" stop-color="white"/><stop offset="100%" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect x="0" y="0" width="100" height="100" fill="url(%23gradient)" /></svg>');
mask-repeat: no-repeat;
mask-size: 100%;
mask-position: center center;
}
.marquee {
.logo-container {
display: flex;
gap: var(--space-14);
&.animate {
animation: marquee var(--marquee-duration) linear infinite;
}
& img {
flex-shrink: 0;
max-width: var(--space-48);
height: var(--space-20);
object-fit: contain;
}
&.reverse-marquee {
animation: marquee-reverse var(--marquee-duration) linear infinite;
}
}
}
@keyframes marquee {
0% {
transform: translateX(0);
}
100% {
transform: translateX(calc(-50%));
}
}
@keyframes marquee-reverse {
0% {
transform: translateX(calc(-50%));
}
100% {
transform: translateX(0);
& img {
flex-shrink: 0;
max-width: var(--space-48);
height: var(--space-20);
object-fit: contain;
}
}
</style>
95 changes: 12 additions & 83 deletions components/LogoTicker.vue
Original file line number Diff line number Diff line change
@@ -1,112 +1,41 @@
<script setup lang="ts">
import { useIntersectionObserver, useResizeObserver } from '@vueuse/core';
import type { BlockLogoCloudLogo } from '~/types/schema/blocks';
import type { File } from '~/types/schema';
import { Vue3Marquee } from 'vue3-marquee';
const props = defineProps<{
logos: BlockLogoCloudLogo[];
}>();
const logoArray = computed(() => {
const blockLogos = unref(props.logos) ?? [];
return [...blockLogos, ...blockLogos];
});
const ticker = ref<HTMLElement | null>(null);
const target = ref<HTMLElement | null>(null);
const tickerWidth = ref<number | null>(null);
const isVisible = ref(false);
useIntersectionObserver(
target,
([{ isIntersecting }]) => {
isVisible.value = isIntersecting;
},
{
threshold: 0.25,
},
);
const duration = computed(() => {
if (tickerWidth.value) {
const calculatedDuration = tickerWidth.value / 60; // 60px per second;
return `${calculatedDuration * 1000}ms`;
} else return '0ms';
});
// Adjust duration on resize
useResizeObserver(ticker, (entries) => {
tickerWidth.value = (entries[0].target as HTMLElement).offsetWidth;
});
</script>

<template>
<div class="block-logocloud-ticker">
<div ref="target" class="marquee-wrapper">
<div
ref="ticker"
:class="[{ animate: isVisible }, 'marquee']"
:style="{
'--marquee-duration': duration,
}"
>
<Vue3Marquee :clone="true" :gradient="true" :gradient-color="[250, 250, 250]" gradient-length="5%">
<div class="logo-container">
<BaseDirectusImage
v-for="logo in logoArray"
v-for="logo in props.logos"
:key="logo.id"
:uuid="(logo.directus_files_id as File).id"
:alt="(logo.directus_files_id as File).description ?? ''"
/>
<div class="logo-spacer"></div>
</div>
</div>
</Vue3Marquee>
</div>
</template>
<style scoped lang="scss">
.block-logocloud-ticker {
position: relative;
display: flex;
overflow: hidden;
.marquee-wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100"><defs><linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="white" stop-opacity="0"/><stop offset="20%" stop-color="white"/><stop offset="80%" stop-color="white"/><stop offset="100%" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect x="0" y="0" width="100" height="100" fill="url(%23gradient)" /></svg>');
mask-repeat: no-repeat;
mask-size: 100%;
mask-position: center center;
}
.marquee {
.logo-container {
display: flex;
gap: var(--space-14);
&.animate {
animation: marquee var(--marquee-duration) linear infinite;
}
& img {
flex-shrink: 0;
max-width: var(--space-48);
height: var(--space-20);
object-fit: contain;
}
}
}
@keyframes marquee {
0% {
transform: translateX(0);
}
100% {
transform: translateX(calc(-50%));
& img {
flex-shrink: 0;
max-width: var(--space-48);
height: var(--space-20);
object-fit: contain;
}
}
</style>
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"dependencies": {
"embla-carousel": "^8.3.1",
"embla-carousel-class-names": "^8.3.1",
"embla-carousel-vue": "^8.3.1"
"embla-carousel-vue": "^8.3.1",
"vue3-marquee": "^4.2.2"
}
}
Loading

0 comments on commit c2552ff

Please sign in to comment.