Разработка систем 3D-визуализации в среде 1С становится всё более актуальной задачей. Это может быть связано с визуализацией складских ячеек, схемами укладки грузов, проектированием простых конструкций (например, для задач сопромата) или отображением сложных аналитических данных. Платформа 1С не имеет встроенного нативного 3D-движка, однако современные механизмы интеграции позволяют использовать мощь веб-технологий внутри прикладных решений.
В этой статье мы подробно разберем, как с помощью стандартного объекта ПолеHTMLДокумента превратить форму 1С в полноценный инструмент 3D-моделирования, рассмотрим выбор между SVG и WebGL, а также решим технические проблемы с производительностью и совместимостью.
Прежде чем приступать к кодингу, проанализируем, какая технология отрисовки лучше подходит под ваши задачи. В рамках платформы 1С у нас есть два основных пути через HTML-поле:
Проанализируем ситуацию: если ваша цель — простые схемы каркасных тел (как в задачах по сопромату), то SVG может быть достаточно. Если же требуется сложная анимация, вращение камеры мышью или работа с мешами, однозначно стоит смотреть в сторону WebGL.
Рассмотрим вариант реализации простой визуализации на SVG. Основная идея заключается в том, что мы формируем XML-структуру и передаем её в ПолеHTMLДокумента. Чтобы избежать полной перерисовки страницы (которая вызывает мерцание), мы будем использовать JavaScript для точечного изменения атрибутов объектов.
Разберем пример кода на стороне 1С, который подготавливает контейнер для графики:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Формируем базовый HTML с контейнером SVG
ТекстHTML =
"<html>
|<body style='margin:0; overflow:hidden;'>
| <svg id='scene' width='100%' height='100%' viewBox='0 0 800 600'>
| <!-- Здесь будут наши элементы -->
| </svg>
|</body>
|</html>";
ЭтаФорма.ПолеВизуализатора = ТекстHTML;
КонецПроцедуры
Для отрисовки 3D-линии в SVG нам нужно пересчитать координаты X, Y, Z в X-экранное и Y-экранное. Рассмотрим упрощенную функцию проекции, которую можно реализовать прямо в JavaScript внутри HTML-поля, чтобы 1С передавала только "чистые" 3D-данные.
Если нам нужна настоящая 3D-сцена, лучше всего интегрировать библиотеку Three.js. Это стандарт де-факто для веб-3D. Рассмотрим, как проинициализировать сцену внутри 1С. Мы не будем подгружать внешние файлы, а вставим код библиотеки или ссылку на CDN в наш HTML-текст.
Проанализируем типовую структуру скрипта для инициализации:
// Внутри текстового реквизита ПолеHTMLДокумента
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Создаем простой каркасный куб
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
Одной из главных проблем является "тормознутость" при передаче данных. Если мы будем обновлять всё свойство Содержимое поля HTML при каждом изменении, страница будет перезагружаться. Чтобы этого избежать, используем метод ИсполнитьJavaScript().
Выясним причину, почему это эффективно: этот метод позволяет вызывать функции внутри уже загруженной страницы без её обновления. Рассмотрим пример передачи новых координат объекта из 1С в 3D-сцену:
&НаКлиенте
Процедура ОбновитьКоординатыОбъекта(ИмяОбъекта, НовоеX, НовоеY, НовоеZ)
// Формируем JSON с данными
Данные = Новый Структура();
Данные.Вставить("id", ИмяОбъекта);
Данные.Вставить("x", НовоеX);
Данные.Вставить("y", НовоеY);
Данные.Вставить("z", НовоеZ);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
СтрJSON = ЗаписьJSON.Закрыть();
// Вызываем JS функцию, которая уже определена в нашем HTML
Элементы.ПолеВизуализатора.ИсполнитьJavaScript("updateObjectPosition(" + СтрJSON + ")");
КонецПроцедуры
В самом JavaScript (внутри HTML) функция будет выглядеть так:
function updateObjectPosition(data) {
let obj = scene.getObjectByName(data.id);
if (obj) {
obj.position.set(data.x, data.y, data.z);
}
}
Часто разработчики сталкиваются с тем, что WebGL "не взлетает" внутри тонкого клиента 1С, хотя в обычном браузере всё работает. Проанализируем ситуацию: 1С использует встроенный движок (в современных версиях это Chromium/Blink), но он может быть ограничен настройками безопасности или отсутствием необходимых системных библиотек.
Основные шаги для исправления работы WebGL:
d3dcompiler_47.dll (или другой версии). Убедитесь, что в системе установлен актуальный DirectX. Иногда помогает копирование этой библиотеки непосредственно в папку с исполняемым файлом платформы bin.Рассмотрим несколько важных моментов, которые помогут сделать ваш визуализатор профессиональным:
1. Использование JSON: Никогда не передавайте данные по одному параметру. Всегда упаковывайте состояние всей сцены или группы объектов в массив структур, преобразовывайте в JSON и передавайте одним вызовом. Это критически важно для производительности анимации.
2. Обратная связь: Если вам нужно, чтобы при клике на 3D-объект в 1С открывалась карточка этого объекта, используйте механизм window.external.Message() или изменение document.location, которое можно перехватить в событии ПриНажатии (в зависимости от режима работы платформы).
3. Предварительный расчет: Если ваша модель статична (например, схема эпюр в сопромате), рассчитайте все координаты узлов на стороне 1С и передайте готовый массив векторов. Оставьте JavaScript-у только задачу отрисовки и вращения камеры.
Подводя итог, можно сказать, что связка 1С + Three.js (WebGL) является наиболее мощным и перспективным решением. Она позволяет создавать интерфейсы, которые по качеству графики не уступают специализированному инженерному софту, оставаясь при этом внутри бизнес-логики учетной системы.