Система мониторинга низкоуглеродных индустриальных парков на основе HTML5 WebGL

Node.js внешний интерфейс JSON WebGL
Система мониторинга низкоуглеродных индустриальных парков на основе HTML5 WebGL

предисловие

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

Woohoo.high topo.com/demo/H TB UI готов…

На этом gif-файле показана система мониторинга энергии низкоуглеродного индустриального парка, которая сочетает в себе 2D и 3D, в основном для мониторинга в режиме реального времени использования воды и электроэнергии каждым зданием и парком в целом.

Код

Создайте сцену

Создать 3D-сцену низкоуглеродного индустриального парка несложно, но как отобразить 2D- и 3D-сцены в одном интерфейсе? Чтобы сделать крутые эффекты, этот метод очень полезен во многих ситуациях.

Вся сцена низкоуглеродного индустриального парка построена на 2D. Мы знаем, что HTML может использовать только традиционные растровые изображения сетки для установки изображений для элементов DOM. Лучше всего реализовывать векторные изображения в формате json. Когда растровое растровое изображение растягивается, увеличены или уменьшены, графика будет размыта, а линии станут толще и появятся зубчатые линии. С другой стороны, векторные изображения описывают графику с помощью точек, линий и многоугольников, поэтому вы можете бесконечно увеличивать и уменьшать масштаб с неизменной точностью.

Сначала я создал 2D-сцену для размещения нашего векторного изображения json и использовал функцию ht.Default.xhrLoad для десериализации векторного фонового изображения json и отображения его на gv.В дополнение к узлу в качестве фона этот векторный фон json изображение имеет Два других узла, как показано на рисунке ниже, больший узел, обведенный красной линией, используется для хранения 3D-сцены, а меньший узел, обведенный правой рамкой, используется для размещения другого gv (еще не используется, позже). Нужно добавить функциональность, например форму формы, поэтому мне нужна фиксированная позиция):

ht.Default.xhrLoad('displays/background.json', function(text) {
    dm.deserialize(text);// 反序列化数据到数据模型

    gv.addToDOM();// 将 2D 场景添加到 body 体中
});

Эта 2D-сцена установлена ​​как фоновая часть.Далее давайте посмотрим, как поставить 3D-сцену на основе 2D-сцены.

Добавьте 3D-сцены в 2D

Также очень легко добавить 3D в 2D, вопрос в том, как заставить 3D-сцену вносить адаптивные изменения в соответствии с масштабированием и переводом 2D-сцены, чтобы 3D-сцена всегда оставалась в фиксированном положении 2D-сцены? Я выполняю автоматические операции макета на 3D-сцене, прослушивая событие изменения свойства gv и прослушивая масштабирование, перевод и другие свойства:

var g3dInfo = create3D('g3dNode');
gv.mp(function(e) {// 监听 gv 的属性变化事件
    if (e.property === 'zoom' || e.property === 'translateX' || e.property === 'translateY' ) {
        layout(g3dInfo);
    }
});

function layout(info) {
    var rect = info.node.getRect(),// 获取场景依赖的节点的 矩形区域
        zoom = gv.getZoom(),// 获取当前 gv 的缩放值
        tx = gv.tx(),// 获取当前 gv 的水平平移值
        ty = gv.ty();// 获取当前 gv 的垂直平移值
    
        // 依赖的节点的大小根据 zoom 缩放值来进行缩放
        rect.x *= zoom,
        rect.y *= zoom,
        rect.width *= zoom,
        rect.height *= zoom;

    var x = rect.x + tx,
        y = rect.y + ty;

    // 设置场景自动布局
    if (info.g3d) info.g3d.layout(x, y, rect.width, rect.height);
}

Внимательные студенты должны были заметить, что я не написал инструкцию для функции create3D.Что касается эффекта отображения, этот метод просто десериализует JSON-рисунок сцены в 3D-сцену и добавляет информацию об объекте для преобразования всех 3D-сцены в 3D-сцену.Зависимый узел и переменные 3D-сцены передаются в:

function create3D(tag) {
    var g3d = new ht.graph3d.Graph3dView();// 3D 组件
    var dataModel = g3d.dm();// 获取 3D 场景的数据容器
    gv.getView().appendChild(g3d.getView());// 将 3D 场景添加到 2D 场景中
    ht.Default.xhrLoad('scenes/电云维.json', function(text) {// 加载 3D 场景的 json 矢量图纸
        dataModel.deserialize(text);// 反序列化数据到数据模型
    });
    
    // 停止事件的传播,阻止它被分派到其他 Document 节点
    g3d.getView().addEventListener('mousedown', function(e) { e.stopPropagation()});
    g3d.getView().addEventListener('mousewheel', function(e) { e.stopPropagation()});
    if (isFirefox=navigator.userAgent.indexOf("Firefox") > 0) {  
        g3d.getView().addEventListener('DOMMouseScroll', function(e) { e.stopPropagation()});
    }

    var info = {
        g3d: g3d,
        node: dm.getDataByTag(tag),
    };
    return info;
}

2D и 3D имеют много одинаковых точек на события мыши, но мы не хотим, чтобы 2D-сцена менялась во время работы с 3D-сценой, поэтому приведенный выше код запрещает распространение событий нажатия мыши и колеса прокрутки.

##Отображение информации о здании

Одна из функций, реализованных системой мониторинга низкоуглеродного индустриального парка: нажмите на вид здания, чтобы переместить здание в более подходящее положение, и на верхней части здания отобразится панель для отображения информации о текущем здании. Здесь я непосредственно создаю узел, который можно отобразить как "заплатку", установив атрибут shape3d узла в Billboard. Панель очень проста в использовании. Во-первых, у нее всего одна грань. Если вам нужен большой количество узлов для отображения данных в 3D-сцене. Рекомендуется использовать этот тип рекламного щита, который очень экономичен.

// 创建在建筑上面的显示面板
var billboard = new ht.Node();
billboard.setScaleX(2);// 将节点 X 轴上放大 2 倍
billboard.setScaleTall(2);// 将节点 Y 轴上放大 2 倍
billboard.s({
    'shape3d': 'billboard',// 此类型为一个面片
    'shape3d.image': 'symbols/nodeForm.json',// 设置面片的显示图片为矢量图片
    'shape3d.autorotate': true,// 始终面向相机
    'shape3d.vector.dynamic': true,// 设置矢量图形
    '3d.visible': false// 不可见
});
billboard.setTag('billboard');// 设置节点的 tag 唯一属性
dataModel.add(billboard);// 将节点添加到数据容器中

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

dataModel.sm().ms(function(e) {// 监听选中变化事件
    if (e.kind === 'set' || e.kind === 'append') {// 设置选中 及 追加选中
        billboard.s('3d.visible', true);
        var data = dataModel.sm().ld();// 获取当前选中的最后一个节点
        if (!data) return;
        billboard.p3(data.getPosition().x, data.getTall() + 200, data.getPosition().y);// 设置 billboard 的位置为当前选中的节点的上方
    }
    else if (e.kind === 'remove') {// 选中移除
        var data = dataModel.sm().ld();// 获取当前最后选中的节点
        if (data) {
            billboard.setPosition(data.getPosition().x, data.getPosition().y);
            billboard.setElevation(data.getTall() + 200);
        }
        else billboard.s('3d.visible', false);
    }
    else if (e.kind === 'clear') billboard.s('3d.visible', false);// 清除所有的选中后设置 billboard 不可见
});

(обратитесь к другим примерам)

woohoo.hightopo.com/demo/large-…

Что касается щелчка по зданию, функция flyTo используется, чтобы подтолкнуть текущую линию обзора к положению узла.Эта функция имеет три параметра в версии 6.2.2.Первый параметр — целевой узел, второй параметр — нужно ли анимировать , а третий параметр - глаз и цель.Расчет расстояния до центра узла, например, следующий код установлен на 0,5, что означает, что глаза динамически вычисляют расстояние в указанном выше направлении, чтобы адаптировать цель к 0,5 экрана. Название здания, на которое нажали в данный момент, отображается в верхней части информационной панели.Я устанавливаю свойство displayName для соответствующего здания при проектировании чертежей 3D-сцены, и текущий дисплей отображается в соответствии с этим displayName.

g3d.mi(function(e) {// 增加交互事件监听器
    if(e.kind === 'clickData'){
        g3d.flyTo(e.data, true, 0.5);// 将 eye 和 center 从当前位置“飞到”目标节点的位置 第二个参数若是1 则占满全屏。 6.2.2 版本以上有此方法
        var name = e.data.getDisplayName();

        // 由于 3D 中不能将模型组合到一起,所以我用追加选中的方法来解决
        dataModel.each(function(node) {
            if(node.getDisplayName() !== name) return;// 我将同一类型的节点的 displayName 设置相同
            dataModel.sm().appendSelection(node);
        })
    }
});

Итак, есть только один рекламный щит, как мы можем заставить этот рекламный щит отображать разную информацию в зависимости от разных зданий? На данный момент есть еще одно преимущество векторных иконок.Динамическое изменение данных осуществляется путем привязки данных к определенной части векторных иконок.Я не могу здесь в двух словах это объяснить.Кратко упомяну как этого добиться В остальном Вы можете перейти к руководству по привязке данных на официальном сайте, чтобы проверить соответствующую информацию и конкретную реализацию.

Свойство shape3d.image было задано для рекламного щита ранее, а установленное изображение — nodeForm.json.В этом json есть четыре строки текста, а текст вверху используется для отображения названия здания, на которое в данный момент нажали.

Согласно руководству, мы знаем, что существует два формата привязки данных: один — тип функции привязки, а другой — тип строки привязки, а именно:

То есть, если нужные нам атрибуты не определены в HT или если на векторной карте есть несколько одинаковых атрибутов, которые нужно изменить на разные значения, атрибуты можно настроить через attr, Здесь я использую этот метод:

"text": {
    "func": "attr@buildingName",
    "value": "赛普健身学院学生宿舍"
}

После завершения привязки данных нам нужно только изменить бизнес-атрибут узла, который в настоящее время ссылается на значок вектора json, в соответствии с данными привязки:

// 不同的楼宇上显示的内容不同
billboard.a('buildingName', name);
billboard.a('electricUsage', (Math.random()*300).toFixed(2));
billboard.a('waterUsage', (Math.random()*300).toFixed(2));
billboard.a('gasUsage', (Math.random()*300).toFixed(2));

Правый дисплей данных

После создания 3D-сцены, как добавить две панели отображения данных справа в 3D? Здесь я добавил еще одну 2D-сцену к узлам, расположенным в предыдущей 2D-сцене json, для отображения общих данных сцены. Поскольку на этом gv есть две информационные панели, я добавил два узла непосредственно в graphView, а узлы добавил в контейнер данных dataModel этого graphView.Я не буду объяснять остальные части, это все базовые коды. :

function createGV(tag) {
    var g2d = new ht.graph.GraphView();// 2D 拓扑场景
    var dataModel = g2d.dm();// 获取当前拓扑场景的数据容器
    gv.getView().appendChild(g2d.getView());// 将此拓扑场景添加到底层背景图上
    g2d.setInteractors([]);// 清除此组件上的交互

    // 添加两个节点到拓扑场景上
    var node = new ht.Node();
    node.setImage('symbols/form.json');
    node.setPosition(0, 0);
    dataModel.add(node);

    var node1 = new ht.Node();
    node1.setImage('symbols/form1.json');
    node1.setPosition(0, dm.getDataByTag(tag).getHeight()/3);
    dataModel.add(node1);

    g2d.fitContent();

    setInterval(function() {// form表单数据动态变化
        node.a('electricUse', (Math.random()*300).toFixed(2));
        node.a('waterUse', (Math.random()*300).toFixed(2));
        node.a('gasUse', (Math.random()*300).toFixed(2));
        node.a('tempUse', (RandomNumBoth(10, 40))+'');
        node.a('wetUse', (Math.floor((Math.random()*100)))+'');
    }, 3000);

    var info = {
        g2d: g2d,
        node: dm.getDataByTag(tag)
    }
    return info;
}

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