• Час читання ~7 хв
  • 12.02.2023

У цій статті я поясню, як інтегрувати адаптивні зображення та прогресивне завантаження зображень у вашому додатку Laravel. Це дасть вашому додатку великий приріст продуктивності. По-перше. Для цього підручника я буду використовувати два дивовижні пакети: Інтервенційне зображення для маніпулювання зображеннями та Lazysizes для прогресивного завантаження зображень. Ви можете слідувати інструкціям з встановлення на відповідних сторінках. Щоб отримати швидкий попередній перегляд того, як ваш додаток відреагує після цього підручника, перегляньте Codefield. Я пройшов цей процес, щоб реалізувати його там. Обов'язково встановіть ці два пакети перед початком процесу. Отже, почнемо.

Форма

<form method="POST" action="{{ url('addPhotos') }}" enctype="multipart/form-data">

{{ csrf_field() }}

<input type="file" name="photo[]"

value="{{ old('photo') }}" multiple="multiple">

<button type="submit">

Add photo(s)

</button>

</form>

this is just a basic form with a post method and action="{{ url('addPhotos') }}" meaning that when the form is submitted it will point to the addPhotos route on your web.php file.

photo is the name of the column on your database where the image path will be saved. the [] stands for multiple if you want to upload multiple photos at once.

завантаження зображення Маршрут

У файлі web.php додайте цей маршрут

Route::post('addPhotos', 'PhotosController@store');

this will set the route for addPhotos and point to the store method in PhotosController.php or whatever controller you have the method in.

Створіть папки

У папці зберігання у вашому додатку створіть папку з іменем public . у цій папці додайте такі папки: medium_photos mobile_photos original_photos large_photos і .tiny_photos Потім на консолі запустітьphp artisan storage:link, щоб створити загальнодоступне посилання між папкою зберігання та спільною папкою. В основному для того, щоб зробити ці фотографії публічними.

Процес

завантаження Тепер тут все відбувається. Я буду мати тут повний метод, а потім загальмувати його для вас.

public function store(Request $request)

{

$this->validate(request(), [

'photo' => 'required'

]); $original_photo_storage = public_path('storage/original_photos/');

$large_photos_storage = public_path('storage/large_photos/');

$medium_photos_storage = public_path('storage/medium_photos/');

$mobile_photos_storage = public_path('storage/mobile_photos/');

$tiny_photos_storage = public_path('storage/tiny_photos/');$files = request()-> file('photo');foreach ($files as $file) { $photo = new Photo; //or whatever your model is called

$photo -> user_id = auth()->id();

$photo -> unique_id = uniqid();

$photo -> photo = $file->hashName(); $image = Image::make($file->getRealPath());

$image->save($original_photo_storage.$file->hashName(),100)->resize(860, null, function ($constraint) {

$constraint->aspectRatio();

})->save($large_photos_storage.$file->hashName(),85)->resize(640, null, function ($constraint) {

$constraint->aspectRatio();

})->save($medium_photos_storage.$file->hashName(),85)->resize(420, null, function ($constraint) {

$constraint->aspectRatio();

})->save($mobile_photos_storage.$file->hashName(),85)->resize(10, null, function ($constraint) {

$constraint->aspectRatio();

})->blur(1)->save($tiny_photos_storage.$file->hashName(),85);

$photo->save();

}

return back();

so let’s brake this down

$this->validate(request(), [

'photo' => 'required'

]);

this is just a validation telling laravel that a photo is required in order to submit the form. You don’t have to add this if you don’t want to.

$original_photo_storage = public_path('storage/original_photos/');

$large_photos_storage = public_path('storage/large_photos/');

$medium_photos_storage = public_path('storage/medium_photos/');

$mobile_photos_storage = public_path('storage/mobile_photos/');

$tiny_photos_storage = public_path('storage/tiny_photos/');

these are the paths to the folders on your public folder.That’s where the images are going to be saved. Now just by the name i guess you know where everything goes.The last folder tiny_photos will be for the tiny images that will be used for progressive image loading.

$files = request()-> file('photo');

this will request the file from the form.

$photo = new Photo; //or whatever your model is called

$photo -> user_id = auth()->id();//create a user id for the photo. //This will be the id of the authenticated user.

$photo -> unique_id = uniqid();//give photo a unique id so you can //reference it when you want to see the photo on your app

$photo -> photo = $file->hashName();//give the uploaded photo a hash //name

$image = Image::make($file->getRealPath());//create a new image //resource from file.This is done by the Intervention Image package

next we save the image

$image->save($original_photo_storage.$file->hashName(),100)//save //the image on the original_photos folder with 100% quality

then we resize the images

->resize(860, null, function ($constraint) {

$constraint->aspectRatio();

})->save($large_photos_storage.$file->hashName(),85)

//we resize the image to 860px, save it to the large_photos folder

//with a quality of 85%.Keep the resized images under 85% to pass //the google lighthouse efficiently compress images requirement.

//there will be no changes in image quality->resize(640, null, function ($constraint) {

$constraint->aspectRatio();

})->save($medium_photos_storage.$file->hashName(),85)

//we resize the image to 640px, save it to the medium_photos folder

//with a quality of 85%.Keep the resized images under 85% to pass //the google lighthouse efficiently compress images requirement.

//there will be no changes in image quality->resize(420, null, function ($constraint) {

$constraint->aspectRatio();

})->save($mobile_photos_storage.$file->hashName(),85)

//we resize the image to 420px, save it to the mobile_photos folder

//with a quality of 85%.Keep the resized images under 85% to pass //the google lighthouse efficiently compress images requirement.

//there will be no changes in image quality->resize(10, null, function ($constraint) {

$constraint->aspectRatio();

})->blur(1)->save($tiny_photos_storage.$file->hashName(),85);

//we resize the image to 10px, save it to the tiny_photos folder

//with a quality of 85%.Keep the resized images under 85% to pass //the google lighthouse efficiently compress images requirement.

//there will be no changes in image quality

//we add the blur(1) method to blur the tiny image for progressive //image loading

then we save everything

$photo->save();

and return back to the form

eturn back();

With this we have uploaded 5 different versions of the image with different sizes that we can use for responsive images.Now we have to call these images based on the screen size.This is one way to go about it.

За допомогою srcset, якщо ви показуєте багато зображень,

вам доведеться зробити цикл.foreach Наприклад

@foreach ($photo as $img)

<img src="{{asset('storage/medium_photos/'.$img->photos)}}"

srcset="{{asset('storage/medium_photos/'.$img->photos.' 860w')}},{{asset('storage/medium_photos/'.$img->photos.' 640w')}},{{asset('storage/mobile_photos/'.$img->photos.' 420w')}}">

@endforeach

or if you are displaying only one image then no need for foreach loop

<img src="{{asset('storage/medium_photos/'.$photo->photos)}}"

srcset="{{asset('storage/medium_photos/'.$photo->photos.' 860w')}},{{asset('storage/medium_photos/'.$photo->photos.' 640w')}},{{asset('storage/mobile_photos/'.$photo->photos.' 420w')}}">

the src element works as a fallback just in case the srcset fails.The srcset element will read the screen size and for any screen that matches the given screen width e.g 860w will load the respective image, in this case will load the large image. and so on for the 640w will load the medium image and for the 420w will load the mobile image.This way you ensure you are not loading a 4k image on a mobile device.That’s just pointless

Елемент

зображення Ще один спосіб зробити це - з елементом

<picture>

<source

media = "(min-width:860px)"

srcset="{{asset('storage/large_photos/'.$photo->photo.' 860w')}}">

<source

media = "(min-width:640px)"

srcset = "{{asset('storage/medium_photos/'.$photo->photo.' 640w')}}" >

<source

media = "(max-width:420px)"

srcset = "{{asset('storage/mobile_photos/'.$photo->photo.' 420w')}}" >

<img src="{{asset('storage/medium_photos/'.$photo->photo)}}" >

</picture>

again in this example the src element will work as a fallback in case srcset fails.I’d say this method is arguably more readable for the browser.We use the <picture> element.Within that we add a <source> element.Within the <source> element we add media where we can compare current screen size against the size defined on the media element and for each screen size, we give the image defined in the srcset element. Taking the example above for all screens larger than 860px we will display the large images, and so it goes on for the rest of the screen sizes. Now, we have yet to implement progressive image loading. Let’s to that now.

зображення Прогресивне завантаження

зображення Після всієї роботи, яку ми виконали, реалізувати прогресивне завантаження зображення легко. В основному вся важка робота здійснюється за допомогою пакету ледачихрозмірів. Додавання прогресивного завантаження зображень дуже схоже на метод відображення адаптивних зображень. Єдина відмінність полягає в тому, що замість використання src ми будемо використовувати і замість srcset цього будемо використовувати data-srcset data-src . Документація Lasysizes докладно пояснює це. Таким чином, одним із методів для цього буде :

зображення Прогресивне завантаження with srcset

<img class="lazyload blur-up" 

src="{{asset('storage/tiny_photos/'.$photo->photos)}}"

data-sizes="auto"

data-src="{{asset('storage/medium_photos/'.$photo->photos)}}"

data-srcset="{{asset('storage/medium_photos/'.$photo->photos.' 860w')}},{{asset('storage/medium_photos/'.$photo->photos.' 640w')}},{{asset('storage/mobile_photos/'.$photo->photos.' 420w')}}"

in this case src element will we only used to load the blurred tiny image and the second the larger image is loaded, the tiny image will disappear and the larger image will take place.

Повідомлення, яке ми використовували class="lazyload blur-up" . У цьому випадку lazyload клас використовується для реалізації прогресивної техніки навантаження. За бажанням можна використовувати методи розмиття або ratio-box fade-box для розмиття blur-up та затухання відповідно. Щоб скористатися цими класами, вам потрібно додати трохи додаткових css до вашого проекту, наприклад:

<style>

.blur-up {

-webkit-filter: blur(5px);

filter: blur(5px);

transition: filter 400ms, -webkit-filter 400ms;

} .blur-up.lazyloaded {

-webkit-filter: blur(0);

filter: blur(0);

}

</style><img src="lqip-src.jpg" data-src="image.jpg" class="lazyload blur-up" /><!-- ... --><style>

.fade-box .lazyload,

.fade-box .lazyloading {

opacity: 0;

transition: opacity 400ms;

} .fade-box img.lazyloaded {

opacity: 1;

}

</style><div class="ratio-box fade-box">

<img src="lqip-src.jpg" />

<img data-src="image.jpg" class="lazyload" />

</div>

but this is very well explained in the documentation.

зображення Прогресивне завантаження with the picture element

<picture>

<source media = "(min-width:860px)"

data-srcset="{{asset('storage/large_photos/'.$photo->photo.' 860w')}}">

<source media = "(min-width:420px)"

data-srcset = "{{asset('storage/medium_photos/'.$photo->photo.' 640w')}}" >

<source media = "(max-width:420px)"

data-srcset = "{{asset('storage/mobile_photos/'.$photo->photo.' 420w')}}" >

<img class="lazyload blur-up"

src="{{asset('storage/tiny_photos/'.$photo->photo)}}"

data-src="{{asset('storage/medium_photos/'.$photo->photo)}}" >

</picture>

Same as before src element will we only used to load the blurred tiny image and the second the larger image is loaded it the tiny image will disappear and the larger image will take place. And instead of using src we will use data-src and instead of srcset we will use data-srcset .

зображення.. І все. Тепер у вас є прогресивне завантаження зображень у поєднанні з адаптивними зображеннями у вашому додатку Laravel, що дає вам великий приріст продуктивності. Поєднайте це з додаванням прогресивної функціональності веб-додатків до свого додатка, і у вас з'явиться дуже швидкий продукт. Сподіваюся, вам сподобався цей підручник. Будь ласка, запитайте мене, якщо у вас є якесь питання або ви щось незрозуміло.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297