Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти
Інше
Події Про нас
Новини 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
0

Коментарі

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

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

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

Project Rules
Новини 07 серпня 2026

Laravel Boost Project Rules: навчіть AI-агентів конвенцій вашого проєкту

У Laravel Boost з'явилися правила проєкту - набір Markdown-файлів із конвенціями вашого застосунку, які AI-агенти читають залежно від контексту роботи. Функція дозволяє зберігати рішення команди та специфічні практики окремо від загальних інструкцій.

Filament v4.12 & v5.7
Новини 07 серпня 2026

Значне покращення продуктивності та виправлення безпеки у Filament v4.12 та v5.7

Команда Filament випустила оновлення v4.12.6 та v5.7.6 з вражаючими покращеннями продуктивності: форми рендеряться на 90% швидше, таблиці - на 52% швидше. Також виправлено низку вразливостей безпеки, тому оновлення критично важливе для всіх користувачів.

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

Rebbix Нова
1 дн. тому

PHP Developer

PHP розробник для європейської компанії, що спеціалізується на рециклінгу та стійкості. Розробка enterprise SaaS платформи з використанням Laravel, SQL, Magento. Потрібна 5+ років досвіду в backend розробці, знання MariaDB/MySQL, product mindset, англійська на рівні advanced.

Digis
9 дн. тому

Senior Laravel Developer (EU based)

Розробка та підтримка frontend та backend компонентів хмарної платформи для управління житловим сектором на Vue.js та Laravel. Вимоги: 5+ років PHP/Laravel, 1+ рік Vue.js, англійська B2+. Обов'язки включають розробку функцій, вдосконалення адмін-панелі, виправлення дефектів та підтримку клієнтських імплементацій.

IT Delight
17 дн. тому

Symfony Developer (German-speaking)

Розробник PHP Symfony з досвідом 5+ років для розробки та оптимізації веб-додатків на Symfony 6+ або Laravel. Потрібен досвід роботи зі Symfony мінімум 2 роки, знання Git, HTML5, CSS3, JavaScript. Бажаний досвід технічного лідерства та роботи в Scrum-командах. Вимога: німецька мова рівня B2 або вище.