Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Новини 07 серпня 2026

Отримання домінантного кольору зображення в Laravel

Зображення, що ще не завантажилося, залишає дірку на сторінці. Звичайні рішення - сірий блок, розмитий thumbnail у HTML або взагалі нічого. Дешевша альтернатива, що покриває більшість потреб - заповнити простір середнім кольором фото. Так макет виглядає навмисним ще до того, як завантажиться перший піксель справжнього зображення.

Laravel 13.24 додав метод dominantColor() до вбудованого API для роботи із зображеннями, який повертає цей колір без окремого пакунка. У цій статті розглянемо, як отримати колір, де його зберігати та як ним користуватися.

Налаштування

Drайвери GD та Imagick компонента для роботі із зображеннями базуються на Intervention Image - це рекомендована, а не обов'язкова залежність:

composer require intervention/image:^4.0

Більше нічого не потрібно. Визначення домінантного кольору працює на обох драйверах.

Отримання домінантного кольору

Викличте dominantColor() на будь-якому екземплярі зображення - отримаєте hex-рядок:

use Illuminate\Support\Facades\Image;
$color = Image::fromPath(storage_path('app/photo.jpg'))->dominantColor();
// "#8a6f4c"

Реалізація зменшує копію зображення до одного пікселя та зчитує його значення. Це саме середнє значення, а не найчастіший колір - тому фото червоного амбара в зеленому полі дасть каламутний оливковий, а не червоний. Для плейсхолдера це саме те, що потрібно: колір має лежати за всім зображенням, а не представляти його об'єкт.

Префікс # завжди включений. Зображення з альфа-каналом повертають восьмизначну форму (#rrggbbaa), тому враховуйте це при визначенні розміру колонки.

Перетворення застосовуються перед вибіркою кольору - ви отримуєте колір зображення, яке збираєтесь зберегти, а не оригіналу:

$color = Image::fromStorage('uploads/photo.jpg')
 ->crop(800, 600, x: 200, y: 0)
 ->dominantColor();

Обріжте небо - і колір зміниться.

Збереження домінантного кольору при завантаженні

Колір корисний лише тоді, коли він доступний при рендерингу сторінки. Тому обчисліть його один раз при завантаженні та зберігайте в моделі. Почніть із колонки:

Schema::create('photos', function (Blueprint $table) {
 $table->id();
 $table->string('path');
 $table->string('dominant_color', 9)->nullable();
 $table->timestamps();
});

Потім у контролері створіть зображення один раз і використовуйте екземпляр повторно:

use App\Models\Photo;

public function store(Request $request)
{
 $request->validate([
 'photo' => ['required', 'image', 'max:12288'],
 ]);

 $photo = $request->image('photo')
 ->orient()
 ->scale(width: 1600)
 ->optimize();

 return Photo::create([
 'path' => $photo->store('photos'),
 'dominant_color' => $photo->dominantColor(),
 ]);
}

Порядок тут важливий: store() виконує pipeline, кешує оброблені байти в екземплярі та очищає pipeline. Наступний виклик dominantColor() на тому ж екземплярі бере ці закешовані байти без додаткової роботи. Поміняйте рядки місцями - і колір обчислюватиметься для одноразового клону pipeline, а store() обробить зображення вдруге. Той самий результат, вдвічі більше роботи.

Значення також мемоізується для кожного екземпляра - повторний виклик dominantColor() нічого не коштує. Оскільки кожне перетворення повертає новий екземпляр, thumbnail, відгалужений від того самого джерела, обчислює власний колір замість успадкування:

$source = Image::fromStorage('uploads/photo.jpg')->orient();
$thumbnail = $source->cover(300, 300);
$display = $source->scale(width: 1600);

$thumbnail->dominantColor(); // вибірка з обрізаного квадрата
$display->dominantColor(); // вибірка з повного кадру

Використання домінантного кольору як плейсхолдера

Маючи колір у моделі, шаблон стає фоновим кольором блоку, що вже має правильне співвідношення сторін:

<div class="aspect-[3/2] overflow-hidden rounded-lg"
 style="background-color: {{ $photo->dominant_color }}">
 <img src="{{ Storage::url($photo->path) }}"
 alt="{{ $photo->caption }}"
 loading="lazy"
 class="h-full w-full object-cover">
</div>

Кольоровий блок малюється з першим кадром, зображення з'являється поверх нього, коли завантажиться, і сторінка ніколи не перебудовується. Це добре поєднується з loading="lazy" у довгій галереї, де більшість зображень не завантажується, поки читач не прокрутить.

Читабельний текст поверх кольору

Підписи чи іконки, розміщені поверх плейсхолдера, мають залишатися розбірливими незалежно від того, це фото снігового поля чи нічного неба. Відносна яскравість дає розумний поріг у кілька рядків:

namespace App\Support;

class Color
{
 public static function isLight(string $hex): bool
 {
 [$r, $g, $b] = sscanf(substr($hex, 0, 7), '#%02x%02x%02x');
 // Rec. 709 luma, 0-255.
 return (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) > 140;
 }
}
<figcaption class="{{ Color::isLight($photo->dominant_color) ? 'text-gray-900' : 'text-white' }}">
 {{ $photo->caption }}
</figcaption>

Заповнення letterbox та обертання

Та сама вибірка доступна як фонове значення всередині перетворення. Передача dominant у contain() заповнює letterbox-смуги власним кольором зображення замість фіксованого, який ви вибрали заздалегідь:

Image::fromUpload($request->file('photo'))
 ->contain(1200, 800, background: 'dominant')
 ->store('photos');

Портретне фото, доповнене до альбомного формату, отримує смуги, що належать фото - це виглядає набагато краще в сітці, ніж білі чи чорні смуги на кожній третій плитці. rotate() приймає те саме значення для кутів, що відкриваються:

$image->rotate(8, background: 'dominant');

В обох випадках вибірка відбувається для зображення на цьому етапі pipeline - обрізка раніше в ланцюжку змінює заповнення.

Що це не є

dominantColor() повертає один усереднений колір. Це не екстрактор палітри, і він не знайде акцентний колір, який вибрав би дизайнер. Якщо вам потрібен набір репрезентативних зразків або перцептивна кластеризація, що ігнорує великий плоский фон - це не та функція, і спеціалізована бібліотека залишається правильним вибором.

Для плейсхолдерів, letterbox-заповнення та тонування картки за її власним зображенням один усереднений колір - це вся робота, і тепер він постачається з фреймворком.

Додаткове читання

  • Практичний посібник з вбудованої обробки зображень Laravel охоплює решту API: зміна розміру, обрізка, конвертація форматів та зберігання
  • Image Dominant Color та підтримка HEIC у Laravel 13.24 містить повні примітки до релізу
  • Функцію додав @dr-codswallop у #60932
6

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

Laravel AI SDK на практиці
Новини 09 жовтня 2026

Laravel AI SDK на практиці: агент, що стоїть за There There

Фрік Ван дер Гертен розповідає, як у Spatie побудували AI-шар хелпдеска There There на Laravel AI SDK: клас агента, інструменти з типізованою JSON-схемою та делегування роботи звичайним domain-діям.

9
CSRF і завантаження
Новини 09 жовтня 2026

Порада з безпеки: як завантаження файлів може обійти захист від CSRF

Стівен Ріс-Картер пояснює, чому файли користувачів варто віддавати з окремого домену: HTML і JS у межах основного застосунку дають доступ до cookie та CSRF-токенів.

18

Вакансії за темою

Hiring Elixir Нова
2 дні тому

WordPress Developer with SEO experience

Розробник WordPress, який відповідатиме за веб-інфраструктуру маркетингових проєктів: розробка, кастомізація та підтримка сайтів, запуск A/B-тестів, покращення швидкості завантаження й SEO. Основний стек: WordPress (теми, плагіни, ACF, custom post types, hooks і filters), PHP, JavaScript, jQuery, MySQL, Git, Figma. Вимоги: досвід SEO, робота з продуктовими та маркетинговими командами, вміння вирішувати технічні проблеми та верстати адаптивні інтерфейси.

Avenga
4 дні тому

Senior PHP Engineer (Drupal)

Розробник на PHP/Drupal з 6+ років досвіду для глобальної платформи. Проектуватиме та розроблятиме масштабовані рішення на Drupal 11, керуватиме власними й контрибьютивними модулями, оптимізуватиме продуктивність, дотримуватиметься стандартів якості й безпеки. Вимоги: досвід з Drupal Core, багатосайтова архітектура, розуміння SDLC, англійська Upper-Intermediate.

Dream-Line
10 днів тому

Php розробник

PHP-розробник для розвитку та супроводу існуючих веб-проєктів. Основна робота на нативному PHP та самописній CMS: допрацювання функціоналу, інтеграція верстки, робота з MySQL, jQuery та AJAX. Потрібен досвід з PHP, ООП, оптимізацією SQL. Фреймворки (Laravel, Symfony) не використовуються.