ایجاد یک گالری عکس مدرن با استفاده از Flexbox و JavaScript
من مدتی در تلاش بودم تا بتوانم با یک افکت مناسب در flexbox یک گالری عکس زیبا ایجاد کنم، طوریکه عکس ها مانند آجرهای دیوار چیده شوند. تلاش اخیرم تقریبا موفقیت آمیز بود، اما پویایی لازم را نداشت.
پس از کار کردن روی مقاله " ایجاد تصاویر تصادفی با استفاده از Flexbox و JavaScript " ، به این فکر افتادم که: چرا از جاوا اسکریپت برای خواندن نسبت ابعاد تصویر و برای تعیین مقدار flex صحیح برای هر عنصر استفاده نکنم؟
ین روش به طراحان این امکان را می دهد که تصاویری با هر اندازه و نسبت ابعاد را داخل یک عنصر container بارگذاری کنند، یک کلاس به آن بدهند و
با استفاده از استانداردهای مدرن وب، بدون نیاز به هیچ پلاگین یا فریم ورک، یک گالری تصاویر یکپارچه ایجاد کنند.
چالش بارگذاری عکس (Loading)
اولین چالش این است که قبل از اینکه جاوا اسکریپت بتواند چیزی را در مورد یک تصویر تعیین کند، آن تصویر باید به طور کامل بر روی یک صفحه بارگذاری شود: فقط داشتن تگ <img> کافی نیست. سه روش برای حل این مسئله وجود دارد :
1. تشخیص اینکه قبل از اجرای JavaScript تمام عناصر لود (بارگذاری) شده باشند.
2. بارگذاری تصاویر با استفاده از خود JavaScript
3. JavaScript را کاملا ترک کنید و ارتفاع و عرض تصاویر سمت سرور را با استفاده از PHP و یا تکنولوژی های مشابه تعیین کنید.
برای مثال من از دو تکنیک اول استفاده می کنم.
من با یک <div> خالی شروع می کنم. تصاویری که داخل این <div> اضافه می شوند دارای عناصر <figure> خواهند بود، بنابراین من استایل ها را تنظیم می کنم:
* { box-sizing: border-box; }
.quantize { display: flex; flex-flow: row wrap; font-size: 0; width:80%; margin: 0 auto; }
.quantize figure { margin: 0; }
.quantize figure img { width: 100%; height: auto; }
اولین قسمت JavaScript :
var container = document.getElementsByClassName('quantize')[0];
var butterflies = [ "orange-butterfly.jpg", "butterfly-on-yellow-flower.jpg", "butterfly-on-petal.jpg", "albino-butterfly.jpg", "blue-butterfly.jpg"];
function preloadImage(filename){
var img=new Image();
img.onload = function(){
img.aspectRatio = img.naturalWidth / img.naturalHeight;
var fig = document.createElement('figure');
fig.appendChild(img);
container.appendChild(fig);
};
img.src= filename;
img.alt = "";
}
function loadImages() {
for (var i = 0; i < butterflies.length; ++i) {
var filename = butterflies[i];
preloadImage(filename);
}
}
دو خط اول کد عنصری را که تصاویر به آن اضافه می شوند شناسایی می کند، و تصاویری را که می خواهیم بارگذاری کنیم به صورت یک آرایه لیست می کند. تابع preloadImage نام فایل ها را از آرایه بیرون می کشد و عناصر تصویر جدید را ایجاد می کند. این روش برای هر تصویر یک ویژگی جدید ایجاد می کند که نسبت بین عرض و ارتفاع تصویر را نشان می دهد. با استفاده از این اطلاعات اضافه شده به تصویر، تابع تصویر را داخل عنصر <figure> قرار می دهد و آن را درون Container اضافه می کند.
دقت کنید که ترتیب مهم است : img.onload باید قبل از تعیین image source ، قرار داده شود.
سپس به تابعی نیاز داریم که تصاویر را به نسبت ابعادشان مرتب کند.
مثال
function fitFlex() {
var flexGroup = container.querySelectorAll("figure");
var flexArray = Array.prototype.slice.call(flexGroup, 0);
flexArray.sort(function (a, b) {
imageAspectRatioA = a.firstElementChild.aspectRatio;
imageAspectRatioB = b.firstElementChild.aspectRatio;
if (imageAspectRatioA < imageAspectRatioB) { return 1; }
if (imageAspectRatioA > imageAspectRatioB) { return -1; }
return 0;
});
var widest = flexArray[0].firstElementChild.aspectRatio;
var smallestWidth = "300";
flexArray.forEach(function(box) {
var flex = 1 / (widest / box.firstElementChild.aspectRatio);
if (flex == 0) { flex = 1; }
boxWidth = smallestWidth * flex;
box.style.cssText = "flex: "+flex+"; min-width:"+boxWidth+"px;
});
}