Уменьшение размера изображений является, пожалуй, первым делом, которое нужно сделать для увеличения скорости загрузки сайта. Скорость загрузки сайта напрямую влияет на его позиции в поисковой системе. 1С Битрикс имеет встроенные инструменты для оптимизации изображений.
При использовании метода сжатия достаточно один раз загрузить страницу с ним, при этом сервер выполнит оптимизацию изображения в соответствии с заданными параметрами и сохранит его в кэш, чтобы в дальнейшем использовать кешированные изображения вместо необжатых файлов.
Использование метода сжатия изображений
<?$renderImg = CFile::ResizeImageGet("ID_КАРТИНКИ", Array("width" => "НОВАЯ_ШИРИНА", "height" => "НОВАЯ ВЫСОТА"), BX_RESIZE_IMAGE_PROPORTIONAL, false); ?>
<img src="<?=$renderImg["src"]?>" alt="Описание картинки"/>
Объявляем переменную renderImg и передаем ей результат работы функции сжатия ResizeImageGet. В качестве параметров передаем функции ID картинки, массив с новыми размерами изображения и тип масштабирования.
Результатом работы функции будет готовая ссылка на кешированную версию исходного изображения, все что нам остается - вставить $renderImg["src"] (путь к картинке) в тег img (ниже будет несколько примеров использования).
Вместо "ID_КАРТИНКИ" может быть подставлено любое значение, например:
- $arResult["PREVIEW_PICTURE"]
- $arResult["DETAIL_PICTURE"]
- $FILE = CFile::GetFileArray( $arResult["DISPLAY_PROPERTIES"]["КОД_СВОЙСТВА"]["VALUE"] );
Типы масштабирования
Лично я достаточно часто использую третий метод изменения размеров, он не обрезает картинку и почти никогда не портит её качество.
- BX_RESIZE_IMAGE_EXACT - масштабирует в прямоугольник $arSize c сохранением пропорций, обрезая лишнее;
- BX_RESIZE_IMAGE_PROPORTIONAL - масштабирует с сохранением пропорций, размер ограничивается $arSize;
- BX_RESIZE_IMAGE_PROPORTIONAL_ALT - масштабирует с сохранением пропорций за ширину при этом принимается максимальное значение из высоты/ширины, размер ограничивается $arSize, улучшенная обработка вертикальных картинок.
Примеры использования
<?
//обрезаем картинку анонса новости
$renderImg = CFile::ResizeImageGet($arResult["PREVIEW_PICTURE"], Array("width" => 300, "height" => 200), BX_RESIZE_IMAGE_PROPORTIONAL_ALT, false); ?>
<img src="<?=$renderImg["src"]?>" alt="<?=$arResult["NAME"]?>"/>
<?
//обрезаем картинку свойства новости и вставляем её в background
$FILE = CFile::GetFileArray($arResult["DISPLAY_PROPERTIES"]["ATT_IMG"]["VALUE"]);
$renderImg = CFile::ResizeImageGet($FILE , Array("width" => 300, "height" => 200), BX_RESIZE_IMAGE_PROPORTIONAL_ALT, false); ?>
<div style="background: url('<?=$renderImg["src"]?>')"></div>
В итоге уменьшенные картинки попадут в папку /upload/resize_cache/путь и при повторных вызовах метод ResizeImageGet будет сразу возвращать путь к уменьшенной версии изображения.
Для достижения еще большей скорости загрузки можно сконвертировать все изображения (в том числе и закешированные уменьшенные версии) в формат WebP, о том как это сделать читайте в нашей статье.
Сжатие картинок прямо внутри статьи по его SRC
Отвечая на вопрос в комментариях "Подскажите, как обжать картинки по ссылке. Например у меня есть статья, где я использую теги <img src"">. Битрикс не дает такой возможности из коробки...", дополняю статью.
Есть решение даже поинтересней. Сделать, помимо вывода сжатой картинки взамен обычной, возможность открытия полноценной при нажатии, для этого необходимо подключить к сайту fanxyBox3 (лежит в открытом доступе, если надо скину ссылку на тот, который я использую).
Важно! Если вы не хотите (по каким-то причинам) оборачивать картинку в FancyBox, то нужно ей добавить класс not_resize. Это учтено в функции resizeImageCallback.
// Функция изменения размера встроенных изображений в тексте
function resizeInlineImages($detailText) {
if (CModule::IncludeModule('main')) {
// Если модуль 'main' подключен, то производим замену встроенных изображений в тексте
$detailText = preg_replace_callback('/(<img[^>]+src="([^"]+)"[^>]*>)/i', 'resizeImageCallback', $detailText);
}
return $detailText; // Возвращаем обработанный текст
}
// Функция поиска ID файла по его пути в БД
function getFileIdBySrc($strFilename){
$strUploadDir = '/'.\Bitrix\Main\Config\Option::get('main', 'upload_dir').'/'; // Получаем директорию для загрузки файлов из настроек Битрикса
$strFile = substr($strFilename, strlen($strUploadDir)); // Обрезаем путь до файла, чтобы получить относительный путь
$connection = \Bitrix\Main\Application::getConnection(); // Получаем объект соединения с БД от Битрикса
$sqlHelper = $connection->getSqlHelper(); // Получаем помощника SQL для экранирования переменных (защита от SQL-инъекций)
$strFile = $sqlHelper->forSql($strFile); // Экранируем переменную для безопасного включения в SQL-запрос
$strSql = "SELECT ID FROM b_file WHERE CONCAT(SUBDIR, '/', FILE_NAME) = '{$strFile}'"; // Формируем SQL запрос. Теперь он безопасен от SQL-инъекций
return $connection->query($strSql)->fetch()['ID']; // Выполняем запрос и возвращаем ID файла
}
// Функция обработки встроенных изображений в тексте с целью изменения их размера и обертывания в тег FancyBox
function resizeImageCallback($matches) {
$imageSrc = $matches[2]; // Получаем путь к изображению из совпадения
$fileID = getFileIdBySrc($imageSrc); // Получаем ID файла по его пути в БД
if ($fileID) {
// Если файл найден, то выполняем изменение его размера
$resizedImage = CFile::ResizeImageGet($fileID, array('width' => 600, 'height' => 400), BX_RESIZE_IMAGE_PROPORTIONAL, true);
if ($resizedImage && isset($resizedImage['src'])) {
// Если удалось изменить размер файла, то заменяем исходный путь на новый и формируем тег
$resizedImageTag = str_replace($imageSrc, $resizedImage['src'], $matches[1]);
$itemClass = 'not_resize';
if (str_contains($matches[1], $itemClass)) {
// Если изображение имеет класс 'not_resize', то возвращаем его без изменений
return $resizedImageTag;
} else {
// Иначе оборачиваем изображение в тег FancyBox
return '<a class="image-block-contain" href="' . $imageSrc . '" data-fancybox="cd__images" rel="nofollow">' . $resizedImageTag . '</a>';
}
} else {
// Если не удалось изменить размер файла, то возвращаем исходное изображение без изменений
return $matches[1];
}
}
}
// использование функций:
$resizedDetailText = resizeInlineImages($arResult['DETAIL_TEXT']);
Как работает код сжатия изображений по их адресу
1. Функция resizeInlineImages($detailText)
принимает детальное описание новости $arResult['DETAIL_TEXT'], которое содержит HTML-код. Затем с помощью регулярного выражения preg_replace_callback находятся все теги IMG в тексте, и для каждого изображения вызывается функция resizeImageCallback
.
2. Функция resizeImageCallback($matches)
вызывается для каждого тега IMG в тексте. Она принимает массив $matches
, который содержит совпадения из регулярного выражения для тега IMG. Сначала функция получает путь к изображению из совпадения $matches[2]
. Затем вызывается функция getFileIdBySrc
, чтобы получить ID файла по его пути в базе данных. Если файл найден, то производится изменение размера изображения с помощью функции CFile::ResizeImageGet
, чтобы получить уменьшенное изображение с заданными параметрами. Затем исходный путь к изображению заменяется на новый путь к уменьшенному изображению, и если изображение не имеет класса 'not_resize', оно оборачивается в тег FancyBox. Если изменение размера изображения не удалось или файл не найден в базе данных, то возвращается исходный тег IMG без изменений.
3. Функция getFileIdBySrc($strFilename)
принимает путь к файлу по его SRC. Сначала она получает директорию для загрузки файлов из настроек Битрикса (папка upload по умолчанию). Затем она создает объект соединения с базой данных и получает помощника SQL для безопасной обработки переменных. Далее формируется SQL-запрос для поиска ID файла по его пути в базе данных, и запрос выполняется с помощью метода query
объекта соединения. Функция возвращает ID файла, если он найден.