Ручное центрирование превьюшек или когда ResizeImageGet() не справляется
Запись от 08.03.2016
Если посмотреть исходный код функции CFile::ResizeImageGet(), то станет ясно, что с ручным центрированием изображений она просто так не справится.
Утрированный пример ситуации, когда это может понадобится: есть горизонтальный блок-превью картинки, а сама картинка вертикальная, и «точка интереса» этой картинки, вовсе не в центре.
Проще говоря, у нас такая картинка (1), а на сайте получаем вот это (2):
Очевидно, что по-хорошему лицо должно быть в центре кадра или около того, но явно не так.
Понимая проблему, мой знакомый попросил исправить это недоразумение на своём сайте, благо - тот на битриксе
Конечно, можно было было по-быстрому хардкодом прописать координаты для каждой фотографии в css и оставить как есть, но я сделал модуль, вот как это выглядит:
По сути, всё что делает модуль - это запоминает связку: id картинки -> позиция x, y.
Что бы в вёрстке картинка принимала нужную позицию нужно исходя из размеров превью (пропорционально(!) уменьшенный оригинал) и размеров блока-превью нужно привести HTML к следующему виду:
И добавить примерно такой js-код:
Здесь js рассчитывает высоту блока, высоту картинки превью, которая подстраивается под ширину блока и на основе данных из админки задаёт смещение для css-свойства background.
P.S.
Сам модуль выложил на github.
Модуль не доделан.
Из критичного:
1. Нет полноценного установщика - не создается highload-инфоблок;
2. Работа в админке довольно глючная, отчасти это связано с отсутствием событий на кнопки редактора (а они, к слову, генерируются js-кодом админки), и отчасти моим поверхностным знанием js;
3. Нужно бы сделать обработку события OnBeforeResizeImage, если всё же делать именно кроп на бекенде.
Поэтому, если будут предложения по улучшению - буду рад услышать советы или критику. На самом деле, только за этим и пишу этот длиннопост.
И если у вас вдруг возникнет желание доделать/расширить/улучшить модуль, присылайте логин с github - добавлю в контрибьюторы
Таблица хайлоада:
Утрированный пример ситуации, когда это может понадобится: есть горизонтальный блок-превью картинки, а сама картинка вертикальная, и «точка интереса» этой картинки, вовсе не в центре.
Проще говоря, у нас такая картинка (1), а на сайте получаем вот это (2):
Очевидно, что по-хорошему лицо должно быть в центре кадра или около того, но явно не так.
Понимая проблему, мой знакомый попросил исправить это недоразумение на своём сайте, благо - тот на битриксе
Конечно, можно было было по-быстрому хардкодом прописать координаты для каждой фотографии в css и оставить как есть, но я сделал модуль, вот как это выглядит:
По сути, всё что делает модуль - это запоминает связку: id картинки -> позиция x, y.
Что бы в вёрстке картинка принимала нужную позицию нужно исходя из размеров превью (пропорционально(!) уменьшенный оригинал) и размеров блока-превью нужно привести HTML к следующему виду:
И добавить примерно такой js-код:
$(document).ready(function () {
// Центрирование изображений по оси Y
imgPositionerByY();
$(window).resize(function() {
imgPositionerByY();
});
});
// Центрирование изображений по оси Y
function imgPositionerByY() {
$('.item-with-photo').each(function() {
var thumb_h = $(this).data('thumb-h');
var thumb_w = $(this).data('thumb-w');
var point_x = $(this).data('point-x');
var point_y = $(this).data('point-y');
var thumbHeightToTarget = thumb_h * point_y / 100;
var aspectThumbToBox = thumb_w / $(this).width();
var thumbHeightInBox = thumbHeightToTarget / aspectThumbToBox;
var halfHeightOfBox = $(this).height() / 2;
var topOffset = -Math.round(Math.abs(thumbHeightInBox - halfHeightOfBox));
$(this).css('background-position', '-50% '+topOffset+'px');
});
}
Здесь js рассчитывает высоту блока, высоту картинки превью, которая подстраивается под ширину блока и на основе данных из админки задаёт смещение для css-свойства background.
P.S.
Сам модуль выложил на github.
Модуль не доделан.
Из критичного:
1. Нет полноценного установщика - не создается highload-инфоблок;
2. Работа в админке довольно глючная, отчасти это связано с отсутствием событий на кнопки редактора (а они, к слову, генерируются js-кодом админки), и отчасти моим поверхностным знанием js;
3. Нужно бы сделать обработку события OnBeforeResizeImage, если всё же делать именно кроп на бекенде.
Поэтому, если будут предложения по улучшению - буду рад услышать советы или критику. На самом деле, только за этим и пишу этот длиннопост.
И если у вас вдруг возникнет желание доделать/расширить/улучшить модуль, присылайте логин с github - добавлю в контрибьюторы
Таблица хайлоада:
/*CREATE TABLE `img_positioner` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`UF_FILE_ID` int(18) DEFAULT NULL,
`UF_POS_X` int(18) DEFAULT NULL,
`UF_POS_Y` int(18) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci*/