add ""masonry"" grid view

This commit is contained in:
Kentai Radiquum 2025-02-01 02:45:41 +05:00
parent a30c9bb445
commit b1ef537d14
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
6 changed files with 189 additions and 51 deletions

View file

@ -32,4 +32,28 @@
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.material-symbols--dashboard-rounded {
display: inline-block;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M14 9q-.425 0-.712-.288T13 8V4q0-.425.288-.712T14 3h6q.425 0 .713.288T21 4v4q0 .425-.288.713T20 9zM4 13q-.425 0-.712-.288T3 12V4q0-.425.288-.712T4 3h6q.425 0 .713.288T11 4v8q0 .425-.288.713T10 13zm10 8q-.425 0-.712-.288T13 20v-8q0-.425.288-.712T14 11h6q.425 0 .713.288T21 12v8q0 .425-.288.713T20 21zM4 21q-.425 0-.712-.288T3 20v-4q0-.425.288-.712T4 15h6q.425 0 .713.288T11 16v4q0 .425-.288.713T10 21z'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.material-symbols--grid-on {
display: inline-block;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M5 21h2.675v-4.675H3V19q0 .825.588 1.413T5 21m4.675 0h4.65v-4.675h-4.65zm6.65 0H19q.825 0 1.413-.587T21 19v-2.675h-4.675zM3 14.325h4.675v-4.65H3zm6.675 0h4.65v-4.65h-4.65zm6.65 0H21v-4.65h-4.675zM3 7.675h4.675V3H5q-.825 0-1.412.588T3 5zm6.675 0h4.65V3h-4.65zm6.65 0H21V5q0-.825-.587-1.412T19 3h-2.675z'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}

View file

@ -557,6 +557,12 @@
.z-\[3\] {
z-index: 3;
}
.\[grid-column\:span_2\] {
grid-column: span 2;
}
.\[grid-row\:span_2\] {
grid-row: span 2;
}
.container {
width: 100%;
@media (width >= 40rem) {
@ -578,6 +584,9 @@
.mx-auto {
margin-inline: auto;
}
.my-2 {
margin-block: calc(var(--spacing) * 2);
}
.my-4 {
margin-block: calc(var(--spacing) * 4);
}
@ -611,12 +620,21 @@
.table {
display: table;
}
.aspect-\[1\/2\] {
aspect-ratio: 1/2;
}
.aspect-\[2\/1\] {
aspect-ratio: 2/1;
}
.aspect-square {
aspect-ratio: 1 / 1;
}
.h-6 {
height: calc(var(--spacing) * 6);
}
.h-8 {
height: calc(var(--spacing) * 8);
}
.h-16 {
height: calc(var(--spacing) * 16);
}
@ -626,6 +644,12 @@
.min-h-16 {
min-height: calc(var(--spacing) * 16);
}
.min-h-48 {
min-height: calc(var(--spacing) * 48);
}
.w-8 {
width: calc(var(--spacing) * 8);
}
.w-16 {
width: calc(var(--spacing) * 16);
}
@ -650,36 +674,6 @@
.resize {
resize: both;
}
.grid-cols-\[repeat\(auto-fill\,1fr\)\] {
grid-template-columns: repeat(auto-fill,1fr);
}
.grid-cols-\[repeat\(auto-fill\,minmax\(1fr\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(1fr,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(5\%\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(5%,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(25\%\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(25%,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(25vw\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(25vw,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(40\%\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(40%,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(40vw\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(40vw,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(45vw\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(45vw,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(50\%\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(50%,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(50vw\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(50vw,1fr));
}
.grid-cols-\[repeat\(auto-fill\,minmax\(250px\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(250px,1fr));
}
@ -689,21 +683,21 @@
.items-center {
align-items: center;
}
.justify-around {
justify-content: space-around;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.gap-1 {
gap: calc(var(--spacing) * 1);
}
.gap-2 {
gap: calc(var(--spacing) * 2);
}
.gap-4 {
gap: calc(var(--spacing) * 4);
}
.gap-6 {
gap: calc(var(--spacing) * 6);
}
.overflow-hidden {
overflow: hidden;
}
@ -751,9 +745,6 @@
.px-4 {
padding-inline: calc(var(--spacing) * 4);
}
.py-2 {
padding-block: calc(var(--spacing) * 2);
}
.py-4 {
padding-block: calc(var(--spacing) * 4);
}
@ -761,10 +752,6 @@
font-size: var(--text-4xl);
line-height: var(--tw-leading, var(--text-4xl--line-height));
}
.text-lg {
font-size: var(--text-lg);
line-height: var(--tw-leading, var(--text-lg--line-height));
}
.text-xl {
font-size: var(--text-xl);
line-height: var(--tw-leading, var(--text-xl--line-height));
@ -779,6 +766,15 @@
.text-\[\#f9ebeb\] {
color: #f9ebeb;
}
.text-gray-200 {
color: var(--color-gray-200);
}
.text-gray-300 {
color: var(--color-gray-300);
}
.text-gray-400 {
color: var(--color-gray-400);
}
.text-orange-500 {
color: var(--color-orange-500);
}
@ -872,6 +868,26 @@
display: block;
}
}
.xl\:flex {
@media (width >= 80rem) {
display: flex;
}
}
.xl\:hidden {
@media (width >= 80rem) {
display: none;
}
}
.xl\:\[grid-auto-flow\:_row_dense\] {
@media (width >= 80rem) {
grid-auto-flow: row dense;
}
}
.xl\:grid-cols-\[repeat\(6\,minmax\(180px\,1fr\)\)\] {
@media (width >= 80rem) {
grid-template-columns: repeat(6,minmax(180px,1fr));
}
}
.xl\:grid-cols-\[repeat\(auto-fill\,minmax\(20\%\,1fr\)\)\] {
@media (width >= 80rem) {
grid-template-columns: repeat(auto-fill,minmax(20%,1fr));
@ -921,6 +937,28 @@
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.material-symbols--dashboard-rounded {
display: inline-block;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M14 9q-.425 0-.712-.288T13 8V4q0-.425.288-.712T14 3h6q.425 0 .713.288T21 4v4q0 .425-.288.713T20 9zM4 13q-.425 0-.712-.288T3 12V4q0-.425.288-.712T4 3h6q.425 0 .713.288T11 4v8q0 .425-.288.713T10 13zm10 8q-.425 0-.712-.288T13 20v-8q0-.425.288-.712T14 11h6q.425 0 .713.288T21 12v8q0 .425-.288.713T20 21zM4 21q-.425 0-.712-.288T3 20v-4q0-.425.288-.712T4 15h6q.425 0 .713.288T11 16v4q0 .425-.288.713T10 21z'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.material-symbols--grid-on {
display: inline-block;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M5 21h2.675v-4.675H3V19q0 .825.588 1.413T5 21m4.675 0h4.65v-4.675h-4.65zm6.65 0H19q.825 0 1.413-.587T21 19v-2.675h-4.675zM3 14.325h4.675v-4.65H3zm6.675 0h4.65v-4.65h-4.65zm6.65 0H21v-4.65h-4.675zM3 7.675h4.675V3H5q-.825 0-1.412.588T3 5zm6.675 0h4.65V3h-4.65zm6.65 0H21V5q0-.825-.587-1.412T19 3h-2.675z'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
@keyframes spin {
to {
transform: rotate(360deg);

View file

@ -6,6 +6,10 @@ async function get(url) {
return await res.json();
}
function getAspect(image) {
return Number(image.naturalWidth / image.naturalHeight);
}
function renderImage(endpoint, bucket, prefix, isrc, iid, placeholder) {
const src = `${endpoint}/${bucket}/${prefix}/${isrc}`;
const loader = placeholder.querySelector(
@ -24,18 +28,71 @@ function renderImage(endpoint, bucket, prefix, isrc, iid, placeholder) {
Img.className = "invisible object-cover w-full h-full absolute inset-0";
Img.loading = "lazy";
const view = getView();
const container = document.getElementById("images_images");
placeholder.appendChild(blurImg);
placeholder.appendChild(Img);
if (view == "masonry") {
container.classList.remove(
"xl:grid-cols-[repeat(auto-fill,minmax(20%,1fr))]"
);
container.classList.add("xl:grid-cols-[repeat(6,minmax(180px,1fr))]");
container.classList.add("xl:[grid-auto-flow:_row_dense]");
blurImg.addEventListener("load", () => {
const aspect = getAspect(blurImg);
if (aspect < 0.95) {
placeholder.classList.remove("aspect-square");
placeholder.classList.add("aspect-[1/2]");
placeholder.classList.add("w-full");
placeholder.classList.add("h-full");
Img.classList.add("object-cover");
blurImg.classList.add("object-cover");
placeholder.classList.add("[grid-row:span_2]");
} else if (aspect > 1.05) {
placeholder.classList.remove("aspect-square");
placeholder.classList.add("aspect-[2/1]");
placeholder.classList.add("w-full");
placeholder.classList.add("h-full");
Img.classList.add("object-cover");
blurImg.classList.add("object-cover");
placeholder.classList.add("[grid-column:span_2]");
}
blurImg.removeEventListener("load", this);
});
}
Img.addEventListener("load", () => {
Img.classList.remove("invisible");
blurImg.remove();
if (view == "grid") blurImg.remove();
loader.remove();
placeholder.href = `/image/?id=${iid}`;
Img.removeEventListener("load", this);
});
}
function setView(view) {
localStorage.setItem("view", view);
}
function getView() {
let view = localStorage.getItem("view");
if (!view || !["grid", "masonry"].includes(view)) {
setView("grid");
view = "grid";
}
const active = document.querySelectorAll(`[data-view="${view}"]`);
if (active.length > 0) {
active.forEach((item) => {
item.classList.add("text-orange-500");
});
}
return view;
}
function setImagesPerPage(count) {
localStorage.setItem("ImagesPP", count);
}
@ -53,7 +110,7 @@ function getImagesPerPage() {
} else if (count) {
url.searchParams.set("ImagesPP", count);
window.history.pushState(
{ offset: getOffset(), ImagesPP: count },
"",
`Wah-Collection/Images`,
`?${url.searchParams.toString()}`
);
@ -104,9 +161,15 @@ function enableNav() {
window.location.href = url.href;
}
function handleClickView(view) {
setView(view);
window.location.reload();
}
const nav_prev = document.querySelectorAll("#nav_prev");
const nav_next = document.querySelectorAll("#nav_next");
const nav_ipp = document.querySelectorAll("#nav_ipp");
const nav_view = document.querySelectorAll("#nav_view");
nav_prev.forEach((item) => {
item.addEventListener("click", handleClickPrev);
@ -117,4 +180,7 @@ function enableNav() {
nav_ipp.forEach((item) => {
item.addEventListener("click", () => handleClickIpp(item.dataset.ipp));
});
nav_view.forEach((item) => {
item.addEventListener("click", () => handleClickView(item.dataset.view));
});
}

View file

@ -10,15 +10,25 @@ export default function PageNav() {
<div className="flex gap-4">
{ipp.map((item, idx) => {
return <button key={`ipp_${item}`}
className={`${idx > 4 ? "hidden md:block" : ""} cursor-pointer md:text-lg lg:text-xl`}
className={`${idx > 4 ? "hidden md:block" : ""} cursor-pointer md:text-lg lg:text-xl text-gray-200`}
id="nav_ipp"
data-ipp={item}
>{item}</button>
})}
</div>
<button className="flex justify-center items-center cursor-pointer" id="nav_next">
<div className="material-symbols--navigate-next w-16 h-16"></div>
</button>
<div className="flex">
<div className="gap-1 hidden xl:flex">
<button className="flex justify-center items-center cursor-pointer text-gray-200" id="nav_view" data-view="grid">
<div className="material-symbols--grid-on w-8 h-8"></div>
</button>
<button className="flex justify-center items-center cursor-pointer text-gray-200" id="nav_view" data-view="masonry">
<div className="material-symbols--dashboard-rounded w-8 h-8"></div>
</button>
</div>
<button className="flex justify-center items-center cursor-pointer" id="nav_next">
<div className="material-symbols--navigate-next w-16 h-16"></div>
</button>
</div>
</div>
);
}

View file

@ -4,7 +4,7 @@ export default function Placeholder(props: {
return (
<a
data-type="placeholder__image"
className={`relative aspect-square min-w-48 sm:min-w-auto rounded-sm overflow-hidden ${
className={`relative aspect-square min-w-48 min-h-48 sm:min-w-auto rounded-sm overflow-hidden ${
props.isMobileHidden ? "hidden xl:block" : ""
}`}
>

View file

@ -6,7 +6,7 @@ export default function ImagesPage() {
<PageNav />
<div
id="images_images"
className="my-4 overflow-hidden grid grid-cols-[repeat(auto-fill,minmax(250px,1fr))] xl:grid-cols-[repeat(auto-fill,minmax(20%,1fr))] sm:items-center sm:justify-center gap-4"
className="my-2 overflow-hidden grid grid-cols-[repeat(auto-fill,minmax(250px,1fr))] xl:grid-cols-[repeat(auto-fill,minmax(20%,1fr))] sm:items-center sm:justify-center gap-2"
></div>
<PageNav />
</>