feat(how-much): added more way to interact with the images

This commit is contained in:
taroj1205 2024-11-11 20:20:07 +13:00
parent d083320e0e
commit d52d737d6d
3 changed files with 89 additions and 13 deletions

View file

@ -30,7 +30,7 @@ import { Image } from "astro:assets";
@tailwind base;
@layer base {
section {
@apply section flex flex-col items-center gap-md;
@apply section flex flex-col items-center gap-md py-20;
}
h2 {

View file

@ -26,6 +26,7 @@ const modes: ModesOptions[] = ["compact", "collapsed", "standard", "split"];
name="view"
value={mode}
checked={mode === "compact"}
class="sr-only"
/>
<span>{mode.charAt(0).toUpperCase() + mode.slice(1)}</span>
</label>
@ -74,6 +75,8 @@ const modes: ModesOptions[] = ["compact", "collapsed", "standard", "split"];
<script>
const radioButtons = document.querySelectorAll('input[name="view"]');
const radioGroup = document.getElementById("radio-group") as HTMLElement;
const labels = radioGroup.querySelectorAll("label");
const imageWrapper = document.getElementById("image-wrapper") as HTMLElement;
const indicators = document.querySelectorAll(".indicator");
const modeOrder = ["compact", "collapsed", "standard", "split"];
@ -127,15 +130,78 @@ const modes: ModesOptions[] = ["compact", "collapsed", "standard", "split"];
});
});
labels.forEach((label) => {
label.addEventListener("mouseenter", (e) => {
if (e.target instanceof HTMLLabelElement) {
const input = e.target.querySelector("input") as HTMLInputElement;
if (input) {
input.checked = true;
updateImages(input.value);
}
}
});
});
indicators.forEach((indicator, index) => {
indicator.addEventListener("click", () => {
updateImages(modeOrder[index]);
});
indicator.addEventListener("mouseenter", () => {
updateImages(modeOrder[index]);
});
});
slider.addEventListener("input", () => {
updateImages(modeOrder[parseInt(slider.value)]);
});
let startX = 0;
let currentX = 0;
let isDragging = false;
imageWrapper.addEventListener("touchstart", (e) => {
startX = e.touches[0].clientX;
isDragging = true;
imageWrapper.style.transition = "none";
});
imageWrapper.addEventListener("touchmove", (e) => {
currentX = e.touches[0].clientX;
const deltaX = (currentX - startX) / 4;
const newTranslateX = deltaX + currentIndex * -100;
const maxTranslateX = (modeOrder.length - 1) * -100;
if (newTranslateX <= 10 && newTranslateX >= maxTranslateX - 10) {
imageWrapper.style.transform = `translateX(${newTranslateX}%)`;
}
});
imageWrapper.addEventListener("touchend", () => {
isDragging = false;
imageWrapper.style.transition = "transform 0.3s ease-in-out";
const deltaX = currentX - startX;
if (deltaX > 50 && currentIndex > 0) {
updateImages(modeOrder[currentIndex - 1]);
} else if (deltaX < -50 && currentIndex < modeOrder.length - 1) {
updateImages(modeOrder[currentIndex + 1]);
} else {
updateImages(modeOrder[currentIndex]);
}
});
imageWrapper.addEventListener("wheel", (e) => {
if (e.deltaY < 0 && currentIndex > 0) {
e.preventDefault();
updateImages(modeOrder[currentIndex - 1]);
} else if (e.deltaY > 0 && currentIndex < modeOrder.length - 1) {
e.preventDefault();
updateImages(modeOrder[currentIndex + 1]);
}
});
</script>
<style>
@ -147,21 +213,21 @@ const modes: ModesOptions[] = ["compact", "collapsed", "standard", "split"];
}
section > div {
@apply flex flex-col gap-md rounded-lg p-6;
@apply flex flex-col gap-md rounded-lg py-6;
}
label {
@apply flex cursor-pointer items-center gap-3 rounded-md p-3 transition-colors hover:bg-gray-100;
@apply flex cursor-pointer items-center gap-3 rounded-md p-3 transition-colors duration-200 hover:bg-secondary;
}
label:has(input:checked) {
@apply bg-secondary;
}
label span {
@apply text-lg;
}
input[type="radio"] {
@apply h-4 w-4 text-secondary focus:ring-secondary;
}
#image-container {
@apply relative aspect-[1.55/1] overflow-clip rounded-lg;
}
@ -171,7 +237,7 @@ const modes: ModesOptions[] = ["compact", "collapsed", "standard", "split"];
}
img {
@apply aspect-[1.55/1] bg-[#272626] object-cover;
@apply aspect-[1.55/1] bg-[#272626] object-cover first:rounded-l-lg last:rounded-r-lg;
}
#radio-group {

View file

@ -49,6 +49,14 @@ module.exports = {
],
dm: ["DM Sans"],
},
fontSize: {
"scale-sm": "clamp(1rem, 2vw, 1.5rem)",
"scale-md": "clamp(1.5rem, 3vw, 2rem)",
"scale-lg": "clamp(3rem, 6vw, 4rem)",
"scale-xl": "clamp(4rem, 8vw, 5rem)",
"scale-2xl": "clamp(5rem, 10vw, 6rem)",
"scale-3xl": "clamp(6rem, 12vw, 7rem)",
},
screens: {
"-sm": { max: "639px" },
"-md": { max: "767px" },
@ -62,13 +70,15 @@ module.exports = {
plugin(({ addBase, addComponents, addUtilities, theme }) => {
addBase({
h2: {
"@apply text-7xl font-bold text-primary": {},
},
p: {
"@apply text-primary": {},
fontSize: `clamp(${theme("fontSize.6xl")}, 10vw, calc(${theme("fontSize.6xl")} + 1rem))`,
"@apply font-bold text-primary leading-none": {},
},
h3: {
"@apply text-5xl font-bold text-primary": {},
fontSize: `clamp(${theme("fontSize.5xl")}, 10vw, calc(${theme("fontSize.5xl")} + 1rem))`,
"@apply font-bold text-primary leading-none": {},
},
p: {
"@apply text-primary leading-none": {},
},
});
addComponents({