Compare commits
2 commits
9d9e00c560
...
c40d7d1ec8
Author | SHA1 | Date | |
---|---|---|---|
c40d7d1ec8 | |||
778e206f9a |
5 changed files with 59 additions and 67 deletions
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
const gallery = document.querySelector('.gallery');
|
const gallery = document.querySelector('.gallery');
|
||||||
const track = gallery.querySelector('.track');
|
const track = gallery.querySelector('.track');
|
||||||
const images = gallery.querySelectorAll('.track > *');
|
const images = Array.from(gallery.querySelectorAll('.track > *'));
|
||||||
const nav = gallery.querySelector('.gallery-nav');
|
const nav = gallery.querySelector('.gallery-nav');
|
||||||
const prevButton = gallery.querySelector('button.prev');
|
const prevButton = gallery.querySelector('button.prev');
|
||||||
const nextButton = gallery.querySelector('button.next');
|
const nextButton = gallery.querySelector('button.next');
|
||||||
|
@ -9,24 +9,16 @@
|
||||||
const TOLERANCE = 2;
|
const TOLERANCE = 2;
|
||||||
|
|
||||||
const debounce = (fn, delay = 300) => {
|
const debounce = (fn, delay = 300) => {
|
||||||
let timer = 0;
|
let timer;
|
||||||
const debounced = (...args) => {
|
return function (...args) {
|
||||||
if (!args) args = [];
|
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(() => fn.apply(fn, args), delay);
|
||||||
timer = setTimeout(() => {
|
|
||||||
fn.apply(fn, args);
|
|
||||||
}, delay);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return debounced;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAtStart = () => Math.floor(track.scrollLeft) <= TOLERANCE;
|
const isAtStart = () => Math.floor(track.scrollLeft) <= TOLERANCE;
|
||||||
const isAtEnd = () => {
|
const isAtEnd = () =>
|
||||||
const { scrollLeft, offsetWidth, scrollWidth } = track;
|
Math.abs(track.scrollLeft + track.offsetWidth - track.scrollWidth) <= TOLERANCE;
|
||||||
return Math.abs(scrollLeft + offsetWidth - scrollWidth) <= TOLERANCE;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateAriaCurrent = (element, index) => {
|
const updateAriaCurrent = (element, index) => {
|
||||||
currentIndex === index
|
currentIndex === index
|
||||||
|
@ -34,7 +26,7 @@
|
||||||
: element.removeAttribute('aria-current');
|
: element.removeAttribute('aria-current');
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateActiveStates = (index) => {
|
const updateActiveStates = () => {
|
||||||
images.forEach(updateAriaCurrent);
|
images.forEach(updateAriaCurrent);
|
||||||
nav.querySelectorAll('.indicator-btn').forEach(updateAriaCurrent);
|
nav.querySelectorAll('.indicator-btn').forEach(updateAriaCurrent);
|
||||||
prevButton.disabled = isAtStart();
|
prevButton.disabled = isAtStart();
|
||||||
|
@ -49,7 +41,7 @@
|
||||||
currentIndex = index;
|
currentIndex = index;
|
||||||
images[index].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
images[index].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
||||||
|
|
||||||
updateActiveStates(index);
|
updateActiveStates();
|
||||||
};
|
};
|
||||||
|
|
||||||
const prev = () => scrollToIndex(currentIndex - 1);
|
const prev = () => scrollToIndex(currentIndex - 1);
|
||||||
|
@ -62,10 +54,10 @@
|
||||||
(entries) => {
|
(entries) => {
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
if (entry.isIntersecting && entry.intersectionRatio >= 0.75) {
|
if (entry.isIntersecting && entry.intersectionRatio >= 0.75) {
|
||||||
const index = [...images].indexOf(entry.target);
|
const index = images.indexOf(entry.target);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
currentIndex = index;
|
currentIndex = index;
|
||||||
updateActiveStates(currentIndex);
|
updateActiveStates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -92,14 +84,14 @@
|
||||||
nav.appendChild(btn);
|
nav.appendChild(btn);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateActiveStates(0);
|
updateActiveStates();
|
||||||
};
|
};
|
||||||
|
|
||||||
images.forEach((el) => galleryObserver.observe(el));
|
images.forEach((el) => galleryObserver.observe(el));
|
||||||
prevButton.addEventListener('click', prev);
|
prevButton.addEventListener('click', prev);
|
||||||
nextButton.addEventListener('click', next);
|
nextButton.addEventListener('click', next);
|
||||||
track.addEventListener('scroll', () => debounce(updateActiveStates(currentIndex)));
|
track.addEventListener('scroll', debounce(updateActiveStates, 100));
|
||||||
document.addEventListener('DOMContentLoaded', () => initializeGallery());
|
document.addEventListener('DOMContentLoaded', initializeGallery);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section aria-label="Image gallery" webc:root="override">
|
<section aria-label="Image gallery" webc:root="override">
|
||||||
|
|
|
@ -52,11 +52,11 @@ gallery: [
|
||||||
---
|
---
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-front.png"
|
:@src="`ref-front.png`"
|
||||||
alt="Sebin Ref"
|
:@alt="`Sebin Ref`"
|
||||||
artist="draftgon"
|
:@artist="`draftgon`"
|
||||||
href="https://bsky.app/profile/draftgon.bsky.social"
|
:@href="`https://bsky.app/profile/draftgon.bsky.social`"
|
||||||
:width="[1000]"
|
:@width="[1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
@ -78,11 +78,11 @@ Sebin has a muscular build that he keeps in shape with regular exercise.
|
||||||
## Wings
|
## Wings
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-back.png"
|
:@src="`ref-back.png`"
|
||||||
alt="Sebin Ref"
|
:@alt="`Sebin Ref`"
|
||||||
artist="draftgon"
|
:@artist="`draftgon`"
|
||||||
href="https://bsky.app/profile/draftgon.bsky.social"
|
:@href="`https://bsky.app/profile/draftgon.bsky.social`"
|
||||||
:width="[1000]"
|
:@width="[1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
@ -96,11 +96,11 @@ Sebin's wings have a span of about 4.17 meters (13'8"). They function very much
|
||||||
## Head
|
## Head
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-expressions.png"
|
:@src="`ref-expressions.png`"
|
||||||
alt="Sebin's expressions"
|
:@alt="`Sebin's expressions`"
|
||||||
artist="draftgon"
|
:@artist="`draftgon`"
|
||||||
href="https://bsky.app/profile/draftgon.bsky.social"
|
:@href="`https://bsky.app/profile/draftgon.bsky.social`"
|
||||||
:width="[1000]"
|
:@width="[1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
@ -114,11 +114,11 @@ Despite what one might expect with reptilians, Sebin's pupils are rounded instea
|
||||||
## Upper body
|
## Upper body
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-upper-body.png"
|
:@src="`ref-upper-body.png`"
|
||||||
alt="Sebin's upper body closeup"
|
:@alt="`Sebin's upper body closeup`"
|
||||||
artist="Nidhogg"
|
:@artist="`Nidhogg`"
|
||||||
href="https://bsky.app/profile/nidthedragon.bsky.social"
|
:@href="`https://bsky.app/profile/nidthedragon.bsky.social`"
|
||||||
:width="[1000]"
|
:@width="[1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
@ -137,10 +137,10 @@ An assortment of additional references how Sebin can be drawn.
|
||||||
|
|
||||||
<ref-gallery>
|
<ref-gallery>
|
||||||
<ref-img webc:for="ref of [...Array(9).keys()]"
|
<ref-img webc:for="ref of [...Array(9).keys()]"
|
||||||
:src="`ref-muscle-${ref + 1}.png`"
|
:@src="`ref-muscle-${ref + 1}.png`"
|
||||||
:alt="$data.gallery[ref].alt"
|
:@alt="$data.gallery[ref].alt"
|
||||||
:width="[500, 1000]"
|
:@width="[500, 1000]"
|
||||||
:href="$data.gallery[ref].href"
|
:@href="$data.gallery[ref].href"
|
||||||
:@artist="$data.gallery[ref].artist"
|
:@artist="$data.gallery[ref].artist"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="false"
|
:@dropshadow="false"
|
||||||
|
@ -150,11 +150,11 @@ An assortment of additional references how Sebin can be drawn.
|
||||||
## Penis
|
## Penis
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-penis.png"
|
:@src="`ref-penis.png`"
|
||||||
alt="Sebin's manly parts"
|
:@alt="`Sebin's manly parts`"
|
||||||
artist="draftgon"
|
:@artist="`draftgon`"
|
||||||
href="https://bsky.app/profile/draftgon.bsky.social"
|
:@href="`https://bsky.app/profile/draftgon.bsky.social`"
|
||||||
:width="[500, 1000]"
|
:@width="[500, 1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
|
|
@ -30,10 +30,10 @@ Sebin knows how to dress!
|
||||||
|
|
||||||
<ref-gallery>
|
<ref-gallery>
|
||||||
<ref-img webc:for="ref of Array(4).keys()"
|
<ref-img webc:for="ref of Array(4).keys()"
|
||||||
:src="`ref-clothes-${ref + 1}.png`"
|
:@src="`ref-clothes-${ref + 1}.png`"
|
||||||
:alt="$data.gallery[ref].alt"
|
:@alt="$data.gallery[ref].alt"
|
||||||
:href="$data.gallery[ref].href"
|
:@href="$data.gallery[ref].href"
|
||||||
:width="[500, 1000]"
|
:@width="[500, 1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@artist="$data.gallery[ref].artist"
|
:@artist="$data.gallery[ref].artist"
|
||||||
:@dropshadow="false"
|
:@dropshadow="false"
|
||||||
|
|
|
@ -5,11 +5,11 @@ eleventyNavigation:
|
||||||
---
|
---
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-overdrive.jpg"
|
:@src="`ref-overdrive.jpg`"
|
||||||
alt="Sebin Overdrive Ref"
|
:@alt="`Sebin Overdrive Ref`"
|
||||||
artist="CVictorrosso"
|
:@artist="`CVictorrosso`"
|
||||||
href="https://bsky.app/profile/cvictorrosso.bsky.social"
|
:@href="`https://bsky.app/profile/cvictorrosso.bsky.social`"
|
||||||
:width="[1000]"
|
:@width="[1000]"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="false"
|
:@dropshadow="false"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
|
|
@ -5,10 +5,10 @@ eleventyNavigation:
|
||||||
---
|
---
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="ref-SFW.png"
|
:@src="`ref-SFW.png`"
|
||||||
alt="Viktor Ref"
|
:@alt="`Viktor Ref`"
|
||||||
artist="sabertoofs"
|
:@artist="`sabertoofs`"
|
||||||
href="https://bsky.app/profile/sabertoofs.bsky.social"
|
:@href="`https://bsky.app/profile/sabertoofs.bsky.social`"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
@ -22,10 +22,10 @@ His forehead, nose, chest, belly and crotch are of light desert sand colors that
|
||||||
His cheeks, shoulders, back and thighs, in contrast, stand out with a rich walnut brown, which is also found on the sides of his tail. From the back of his head, down his spine and across the top of his tail is a continuous strip of deep dark cedar brown. Arms and legs are distinguished by a light earthy brown.
|
His cheeks, shoulders, back and thighs, in contrast, stand out with a rich walnut brown, which is also found on the sides of his tail. From the back of his head, down his spine and across the top of his tail is a continuous strip of deep dark cedar brown. Arms and legs are distinguished by a light earthy brown.
|
||||||
|
|
||||||
<ref-img
|
<ref-img
|
||||||
src="pinup-SFW.png"
|
:@src="`pinup-SFW.png`"
|
||||||
alt="Viktor Ref"
|
:@alt="`Viktor Ref`"
|
||||||
artist="sabertoofs"
|
:@artist="`sabertoofs`"
|
||||||
href="https://bsky.app/profile/sabertoofs.bsky.social"
|
:@href="`https://bsky.app/profile/sabertoofs.bsky.social`"
|
||||||
:@char="$data.firstName.toLowerCase()"
|
:@char="$data.firstName.toLowerCase()"
|
||||||
:@dropshadow="true"
|
:@dropshadow="true"
|
||||||
></ref-img>
|
></ref-img>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue