При разработке интерфейсов на управляемых формах «1С:Предприятие 8» программисты часто сталкиваются с неприятной особенностью: картинки, которые отлично масштабируются в обычном поле формы, в ячейках таблиц и динамических списков выводятся в своем реальном (исходном) размере. Если пользователь загрузил фотографию товара высокого разрешения, строка списка растягивается на весь экран либо изображение просто обрезается по границам ячейки. Это ломает визуальную структуру формы и делает работу пользователей крайне неудобной.
В этой статье мы подробно разберем, почему так происходит, рассмотрим архитектурные особенности работы динамических списков и изучим практические методы решения этой проблемы — от классических способов с использованием внешних компонент до современных кроссплатформенных механизмов самой платформы 1С.
Давайте проанализируем ситуацию с точки зрения платформы. В обычном поле формы разработчик имеет возможность жестко задать ширину и высоту элемента управления, а платформа берет на себя задачу по пропорциональному сжатию или растяжению картинки в соответствии со свойством РазмерКартинки (например, в значениях Пропорционально или Авто).
В табличной части или динамическом списке ситуация иная. Динамический список спроектирован как высокопроизводительный объект для максимально быстрого вывода больших массивов данных. Каждая строка списка формируется "на лету". Если бы платформа пыталась выполнять на клиенте динамическое масштабирование и перерисовку сотен тяжелых графических файлов при каждом скроллинге, интерфейс программы моментально бы завис.
Именно поэтому для ячеек таблиц действуют строгие ограничения. Платформа выводит изображение "как есть" в его исходном разрешении, ориентируясь на настройки высоты строки и ширины колонки. Чтобы интерфейс оставался отзывчивым, а картинки выглядели аккуратно, разработчику необходимо самостоятельно позаботиться о подготовке уменьшенных копий — миниатюр (превью) изображений.
Если вы работаете на современных версиях платформы, вам больше не нужно использовать внешние утилиты или COM-объекты. Начиная с версии 14 технологической платформы 8.3, в распоряжении разработчиков появился мощный кроссплатформенный механизм — объект ОбрабатываемаяКартинка. Он работает как на Windows, так и на Linux-серверах.
Рассмотрим по шагам, как программно изменить размер картинки на сервере при ее загрузке в базу данных и сохранить готовую миниатюру:
// Функция принимает исходную картинку и возвращает уменьшенную копию (миниатюру)
Функция ПолучитьМиниатюруКартинки(ДанныеИсходнойКартинки, НужнаяШирина = 100) Экспорт
// Создаем объект Картинка из двоичных данных или файла
ИсходнаяКартинка = Новый Картинка(ДанныеИсходнойКартинки);
// Инициализируем объект для обработки графики
ОбработкаГрафики = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
// Изменяем размер. Второй параметр (высота) устанавливаем в Неопределено,
// чтобы платформа автоматически рассчитала высоту с сохранением пропорций.
ОбработкаГрафики.УстановитьРазмер(НужнаяШирина, Неопределено);
// Получаем готовую миниатюру
Миниатюра = ОбработкаГрафики.ПолучитьКартинку();
Возврат Миниатюра.ПолучитьДвоичныеДанные();
КонецФункции
Полученные двоичные данные миниатюры мы сохраняем в отдельный реквизит справочника (например, ФайлМиниатюры) параллельно с основным файлом. В динамический список мы выводим именно это поле-миниатюру. Это решает проблему масштабирования и кардинально снижает нагрузку на сеть и оперативную память.
Если ваша конфигурация работает на старых версиях платформы (ниже 8.3.14), где объект ОбрабатываемаяКартинка еще недоступен, отличным решением для операционных систем семейства Windows станет использование штатного COM-объекта WIA.ImageFile и фильтра масштабирования. Этот метод не требует регистрации сторонних DLL-библиотек вроде ImageMagick, так как библиотека WIA предустановлена в Windows по умолчанию.
Разберем пример создания миниатюры с использованием фильтра масштабирования WIA:
Функция ИзменитьРазмерКартинкиЧерезWIA(ПутьКФайлу, ПутьКРезультату, НоваяШирина, НоваяВысота) Экспорт
Попытка
// Создаем объекты для работы с изображением и фильтрами
ИзображениеWIA = Новый COMОбъект("WIA.ImageFile");
ПроцессорWIA = Новый COMОбъект("WIA.ImageProcess");
// Загружаем файл во внутренний буфер COM-объекта
ИзображениеWIA.LoadFile(ПутьКФайлу);
// Добавляем фильтр масштабирования (Scale)
ФильтрМасштабирования = ПроцессорWIA.FilterInfos("Scale").FilterID;
ПроцессорWIA.Filters.Add(ФильтрМасштабирования);
// Настраиваем параметры фильтра
ПроцессорWIA.Filters(1).Properties("MaximumWidth").Value = НоваяШирина;
ПроцессорWIA.Filters(1).Properties("MaximumHeight").Value = НоваяВысота;
ПроцессорWIA.Filters(1).Properties("KeepAspectRatio").Value = Истина; // Сохраняем пропорции
// Применяем фильтр к исходному изображению
ИзображениеWIA = ПроцессорWIA.Apply(ИзображениеWIA);
// Сохраняем полученный результат на диск
Если НайтиФайлы(ПутьКРезультату).Количество() > 0 Тогда
УдалитьФайлы(ПутьКРезультату);
КонецЕсли;
ИзображениеWIA.SaveFile(ПутьКРезультату);
Возврат Истина;
Исключение
ЗаписьЖурналаРегистрации("РесайзКартинки", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Ложь;
КонецПопытки;
КонецФункции
Этот метод отлично зарекомендовал себя на практике. Он работает стабильно, не требует установки дополнительного ПО на сервер и позволяет быстро генерировать превью-картинки перед их сохранением в базу данных.
В высоконагруженных системах с миллионной номенклатурой хранение картинок внутри базы данных СУБД приводит к взрывному росту объема базы (база начинает весить терабайты, что усложняет обслуживание и создание бэкапов). Современный подход предполагает вынос медиафайлов во внешние объектные хранилища (например, AWS S3, MinIO) или использование специализированных CDN-сервисов (таких как cloudimage.io).
При таком подходе в базе 1С хранится только уникальный идентификатор картинки или путь к ней. Запрос картинки динамическим списком происходит по URL-адресу. Преимущество специализированных сервисов CDN заключается в том, что они умеют масштабировать картинки "на лету" по параметрам, указанным прямо в строке запроса.
Проанализируем пример формирования URL для динамического списка:
https://my-storage.com/images/product_10293.jpghttps://cdn.my-storage.com/width/60/height/60/product_10293.jpgВ результате клиентское приложение 1С скачивает из сети уже сжатый и оптимизированный под размеры ячейки файл, тратя минимум сетевого трафика и оперативной памяти.
Чтобы ваши динамические списки работали быстро и не вызывали зависаний у пользователей, рекомендуем придерживаться следующих правил:
ПолучитьНавигационнуюСсылку(ОбъектСсылка, "ИмяРеквизитаХранилища")).Применяя эти подходы, вы сможете создавать не только красивые, но и высокопроизводительные интерфейсы, которые будут работать плавно на любых компьютерах пользователей.