feat: update RefGallery to native scrolling
This commit is contained in:
parent
c77854667b
commit
d84c415b22
1 changed files with 58 additions and 13 deletions
|
@ -1,30 +1,64 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { debounce } from "@/helpers";
|
||||
|
||||
const activeImage = ref(0);
|
||||
const images = ref<Array<Element>>([]);
|
||||
const element = document.createElement("div");
|
||||
const galleryViewport = ref<HTMLElement>(element);
|
||||
const galleryItemWidth = ref<number>(1);
|
||||
|
||||
const offset = computed(() => `margin-left: -${activeImage.value * 100}%`);
|
||||
const resizeObserverCallback = (entries: Array<ResizeObserverEntry>): void => {
|
||||
for (const entry of entries) {
|
||||
galleryItemWidth.value = entry.contentRect.width;
|
||||
}
|
||||
};
|
||||
|
||||
const setActive = (index: number) => {
|
||||
const resizeObserver = new ResizeObserver(
|
||||
debounce(resizeObserverCallback, 1000)
|
||||
);
|
||||
|
||||
const setActiveImage = (index: number): void => {
|
||||
activeImage.value = index;
|
||||
galleryViewport.value.scrollTo({
|
||||
left: galleryItemWidth.value * index,
|
||||
behavior: "smooth",
|
||||
});
|
||||
};
|
||||
const prev = () => {
|
||||
|
||||
const getActiveImage = (gallery: HTMLElement, itemWidth: number): number => {
|
||||
return gallery.scrollLeft / itemWidth;
|
||||
};
|
||||
|
||||
const prev = (): void => {
|
||||
if (activeImage.value > 0) {
|
||||
activeImage.value -= 1;
|
||||
galleryViewport.value.scrollBy({
|
||||
left: galleryItemWidth.value * -1,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
};
|
||||
const next = () => {
|
||||
|
||||
const next = (): void => {
|
||||
if (activeImage.value < images.value.length - 1) {
|
||||
activeImage.value += 1;
|
||||
galleryViewport.value.scrollBy({
|
||||
left: galleryItemWidth.value,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onScroll = (): void => {
|
||||
const newImg = getActiveImage(galleryViewport.value, galleryItemWidth.value);
|
||||
setActiveImage(newImg);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const sel = ".gallery__viewport .figure";
|
||||
const elements = document.querySelectorAll(sel);
|
||||
const imageArray = Array.from(elements);
|
||||
images.value = imageArray;
|
||||
resizeObserver.observe(galleryViewport.value);
|
||||
images.value = Array.from(galleryViewport.value.children);
|
||||
galleryItemWidth.value =
|
||||
galleryViewport.value.scrollWidth / images.value.length;
|
||||
galleryViewport.value.addEventListener("scroll", debounce(onScroll, 100));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -44,7 +78,7 @@ onMounted(() => {
|
|||
v-show="activeImage < images.length - 1"
|
||||
></a>
|
||||
|
||||
<div class="gallery__viewport" :style="offset">
|
||||
<div class="gallery__viewport" ref="galleryViewport">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -55,7 +89,7 @@ onMounted(() => {
|
|||
<a
|
||||
href="#"
|
||||
:class="{ active: activeImage === idx }"
|
||||
@click.prevent="setActive(idx)"
|
||||
@click.prevent="setActiveImage(idx)"
|
||||
></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -105,7 +139,16 @@ onMounted(() => {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
overflow: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
|
||||
scrollbar-width: none;
|
||||
|
||||
transition: 0.3s all ease-in-out;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.figure {
|
||||
|
@ -113,6 +156,8 @@ onMounted(() => {
|
|||
padding: var(--gallery-image-padding);
|
||||
flex: 1 0 100%;
|
||||
|
||||
scroll-snap-align: center;
|
||||
|
||||
&__meta {
|
||||
text-align: center;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue