Как исправить некорректное масштабирование картинки в дереве значений на управляемой форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработчики при проектировании интерфейсов на управляемых формах часто сталкиваются с неприятной особенностью платформы «1С:Предприятие 8»: при выводе изображений в ячейки табличных частей, таблиц или деревьев значений стандартные свойства масштабирования работают некорректно. Настройки элемента формы, такие как РазмерКартинки (значения Пропорционально, Авторазмер, Черепица) или Масштабировать, зачастую попросту игнорируются, если картинка находится внутри строки динамической таблицы.

В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем ограничения платформы и рассмотрим несколько эффективных способов решения — от современных штатных механизмов до альтернативных вариантов построения интерфейса.

Выясняем причину: почему стандартные свойства не работают в таблицах?

Поведение платформы 1С при отрисовке картинок в строках табличного поля жестко привязано к оптимизации интерфейса и производительности рендеринга. Давайте разберем два основных сценария, с которыми сталкивается разработчик:

  1. Высота строки установлена по умолчанию («Авто» или 0): В этом режиме платформа принудительно сжимает любое переданное изображение до стандартного системного размера иконки (обычно это 16х16 пикселей). Это делается для того, чтобы строки таблицы оставались компактными, а текст не «расползался». Никакие настройки пропорциональности при этом не срабатывают.
  2. Высота строки зафиксирована вручную (например, установлена в значение 3, 5 или более): Если мы передаем в ячейку полноценное изображение (например, фото номенклатуры из базы данных), платформа пытается отобразить его в реальном размере (100%). Картинка при этом не масштабируется под высоту строки. В результате изображение либо обрезается границами ячейки, либо начинает перекрывать соседние строки и элементы интерфейса, полностью ломая визуальное представление формы.

Автоматическое и качественное пропорциональное масштабирование динамических картинок «на лету» внутри ячеек таблиц штатными свойствами отображения в 1С изначально не было предусмотрено. Поэтому нам приходится применять программные методы подготовки изображений или пересматривать архитектуру интерфейса.

Способ 1. Современное решение: Использование объекта «ОбрабатываемаяКартинка» (начиная с версии 8.3.14)

Если в старых версиях платформы (до 8.3.14) разработчикам приходилось использовать внешние компоненты, библиотеки Windows (GDI/WIA) или утилиты командной строки, то в современных релизах появился отличный кроссплатформенный инструмент — объект встроенного языка ОбрабатываемаяКартинка.

Этот объект позволяет изменять физический размер (разрешение) картинки прямо на стороне сервера (включая сервера под управлением ОС Linux). Мы можем пропорционально сжать картинку до нужного размера перед тем, как поместить её в реквизит дерева значений.

Рассмотрим пример кода, который сжимает исходное изображение до ширины 64 пикселя с сохранением пропорций:


&НаСервере
Функция ПолучитьСжатуюКартинку(ДвоичныеДанныеКартинки) Экспорт
    
    // Создаем объект Картинка из исходных двоичных данных
    ИсходнаяКартинка = Новый Картинка(ДвоичныеДанныеКартинки);
    
    // Инициализируем объект для обработки
    Обработка = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
    
    // Устанавливаем целевой размер. 
    // Второй параметр (высота) передаем как Неопределено — 
    // в этом случае платформа смасштабирует высоту пропорционально ширине.
    Обработка.УстановитьРазмер(64, Неопределено);
    
    // Получаем измененную картинку
    РезультатКартинка = Обработка.ПолучитьКартинку();
    
    Возврат РезультатКартинка;
    
КонецФункции

После этого полученную сжатую картинку можно преобразовать в двоичные данные, поместить во временное хранилище и передать адрес в соответствующую колонку дерева значений. При фиксированной высоте строки таблицы (например, значение высоты строки 3 или 4) такое превью отобразится идеально ровно и без искажений.

Способ 2. Оптимальный подход: Кэширование превью для больших баз данных

Представим ситуацию, когда в базе данных хранится большое количество картинок (например, 75 000 изображений номенклатуры, как у автора темы). Если мы будем масштабировать эти картинки с помощью ОбрабатываемаяКартинка «на лету» прямо при заполнении дерева значений или при выводе строк на экран, это приведет к катастрофическому падению производительности.

Сервер будет перегружен операциями ресайза, а пользователь столкнется с задержками (фризами) при открытии формы и прокрутке дерева. Чтобы избежать этого, реализуем правильную архитектуру хранения:

  1. Создадим в базе данных (например, в справочнике присоединенных файлов или специальном регистре сведений) дополнительный реквизит с типом ХранилищеЗначения для хранения уменьшенной копии (миниатюры/превью) изображения. Оптимальный размер превью — 64х64 или 128х128 пикселей.
  2. Генерацию превью будем выполнять один раз — в момент записи основного изображения номенклатуры в базу данных. Для существующих 75 000 картинок напишем разовую обработку, которая обойдет базу и создаст миниатюры.
  3. При заполнении дерева значений на управляемой форме будем считывать и выводить исключительно готовые миниатюры по их навигационным ссылкам. Это обеспечит моментальное открытие формы и плавный скроллинг дерева.

Посмотрим на пример кода обработки, выполняющей предварительное создание превью:


&НаСервере
Процедура СгенерироватьПревьюДляВсехКартинок()
    
    Выборка = Справочники.НоменклатураПрисоединенныеФайлы.Выбрать();
    Пока Выборка.Следующий() Цикл
        
        // Получаем файл из базы данных
        ДвоичныеДанныеФайла = Выборка.ФайлХранилище.Получить();
        Если ТипЗнч(ДвоичныеДанныеФайла) <> Тип("ДвоичныеДанные") Тогда
            Продолжить;
        КонецЕсли;
        
        Попытка
            // Масштабируем изображение
            КартинкаОбъект = Новый Картинка(ДвоичныеДанныеФайла);
            Обработка = Новый ОбрабатываемаяКартинка(КартинкаОбъект);
            Обработка.УстановитьРазмер(128, 128); // Фиксированный квадратный размер для сетки
            
            Миниатюра = Обработка.ПолучитьКартинку();
            
            // Записываем миниатюру в базу данных (в специальный реквизит)
            ОбъектФайла = Выборка.ПолучитьОбъект();
            ОбъектФайла.ХранилищеПревью = Новый ХранилищеЗначения(Миниатюра.ПолучитьДвоичныеДанные());
            ОбъектФайла.Записать();
        Исключение
            // Обработка ошибок, если файл оказался не картинкой или поврежден
            ЗаписьЖурналаРегистрации("РесайзКартинок", УровеньЖурналаРегистрации.Предупреждение,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        КонецПопытки;
        
    КонецЦикла;
    
КонецПроцедуры

Способ 3. Изменение UX/UI: Отображение картинки при активизации строки

Если по каким-то причинам изменять базу данных или генерировать превью нельзя, можно применить альтернативный паттерн проектирования интерфейса. Вместо того чтобы пытаться втиснуть картинку в каждую строку дерева значений, сделаем дерево максимально компактным (без колонки с картинкой), а само изображение будем выводить в отдельной области формы.

Для этого выполним следующие шаги:

  1. Разместим на управляемой форме дерево значений в левой части.
  2. В правой части формы добавим декоративный элемент — одиночное Поле картинки (связанное с реквизитом формы типа Строка, содержащим адрес во временном хранилище).
  3. Для одиночного поля картинки на форме установим свойство РазмерКартинки в значение Пропорционально. На одиночных элементах (вне таблиц) это свойство работает безупречно.
  4. Создадим обработчик события дерева значений ПриАктивизацииСтроки. При перемещении пользователя по строкам дерева будем оперативно считывать картинку текущей номенклатуры и помещать её адрес в поле картинки на форме.

Посмотрим на программную реализацию этого подхода:


&НаКлиенте
Процедура ДеревоНоменклатурыПриАктивизацииСтроки(Элемент)
    
    ТекущиеДанные = Элементы.ДеревоНоменклатуры.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Вызываем серверный метод для получения адреса картинки текущей номенклатуры
        АдресКартинкиНаФорме = ПолучитьАдресКартинкиНаСервере(ТекущиеДанные.Номенклатура);
    Иначе
        АдресКартинкиНаФорме = "";
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьАдресКартинкиНаСервере(Знач ТекущаяНоменклатура)
    
    // Получаем двоичные данные изображения из базы данных
    ДвоичныеДанные = ПолучитьДвоичныеДанныеКартинкиНоменклатуры(ТекущаяНоменклатура);
    
    Если ДвоичныеДанные <> Неопределено Тогда
        // Помещаем во временное хранилище и возвращаем адрес для отображения на форме
        Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанные);
    КонецЕсли;
    
    Возврат "";
    
КонецФункции

Этот способ крайне дружелюбен к производительности. Картинка считывается и передается на клиент только для одной — текущей — позиции номенклатуры, а дерево значений остается быстрым и информативным.

Способ 4. Вывод дерева через Поле HTML-документа

Для продвинутых разработчиков, которым принципиально важно выводить полноценный интерактивный каталог с крупными картинками непосредственно в табличном виде, существует обходной путь через использование элемента формы с видом Поле HTML-документа.

В этом сценарии мы формируем дерево или таблицу программно на сервере в виде HTML-кода с использованием CSS-стилей. В разметке HTML масштабирование картинок под размеры ячейки реализуется невероятно просто с помощью стандартных CSS-свойств, например:


<style>
    .grid-image {
        max-width: 100%;
        max-height: 80px;
        object-fit: contain;
    }
</style>

Платформа 1С отобразит сгенерированный HTML-код внутри поля формы, сохранив все заданные пропорции картинок. При этом интерактивность (клики по строкам, выбор элементов) можно обрабатывать с помощью встроенных механизмов перехвата событий HTML-документа.

Подведем итог: несмотря на очевидную недоработку платформы в части автоматического масштабирования картинок внутри таблиц «из коробки», у разработчиков есть арсенал мощных инструментов. Для современных конфигураций идеальным выбором будет сочетание объекта ОбрабатываемаяКартинка и механизма кэширования превью, а для интерфейсной оптимизации отлично подойдет вывод картинки текущей строки в отдельную область формы.

← На главную