Очень большой вложенный массив ngFor SVG: проблемы с производительностью, вопрос архитектуры - PullRequest
1 голос
/ 04 февраля 2020

Я работаю над приложением Entreprise, где мне нужно динамически визуализировать SVG. SVG используется для отображения планов этажей. Элементы SVG описаны в базе данных и предоставлены внешнему интерфейсу способом JSON, позволяющим отображать графику с использованием шаблонов.

Я не использую теги <img>, потому что мне нужно динамически изменять некоторые атрибуты типа viewBox и transform.

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

Шаблон супер базовый c, он состоит из первого ngFor l oop, который необходимо создать <g> элементов, а затем зацикливание на вложенных объектах, описывающих другие объекты SVG (круги, пути, тексты ...)

В моем текущем примере первый ngFor зацикливает более 800 объектов, каждый последующий ngFor циклы от 1 до 5 объектов.

Визуализация шаблона мучительно медленная (это занимает около 8 секунд). Проблема в том, что мне нужно восстановить простой SVG во внешнем интерфейсе. Я использую <defs> и <use> всякий раз, когда это возможно, но это не уменьшает количество циклов, которые я должен сделать.

Ниже приведена часть шаблона:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="...">
  <g *ngFor="let layer of layers$ | async">
    <g *ngFor="let group of groups$ | async"
       [attr.id]="group.id"
       [attr.stroke]="group!.stroke"
       [attr.stroke-width]="group!.strokeWidth"
       [attr.fill]="group!.fill">

      <ng-container *ngFor="let entity of groups.entities" ngSwitch]="entity.entityType">

        <line *ngSwitchCase="SVG_ENTITY_TYPES.line"
              [attr.x1]="entity.startPoint.x"
              [attr.x2]="entity.endPoint.x"
              [attr.y1]="entity.startPoint.y"
              [attr.y2]="entity.endPoint.y"
              [attr.stroke-width]="entity.strokeWidth" />

        <path *ngSwitchCase="SVG_ENTITY_TYPES.path"
              [attr.d]="entity.data" />

        <!-- Other entity types -->

      </ng-container>
    </g>
  </g>
</svg>

Ниже приведен пример узла из набора данных, объект с "id": 42 является группой. Массив groups содержит сотни из них. Эта группа примеров имеет только одну сущность SVG, но в реальном наборе данных она может содержать несколько сущностей.

{
    "id": 42,
    "layerId": 1,
    "fill": "black",
    "stroke": null,
    "strokeWidth": null,
    "entities": [{
        "stroke": null,
        "strokeWidth": 0.1,
        "entityType": 3,
        "transform": {
            "rotationAngle": 0.0,
            "rotationCenter": null,
            "translate": null,
            "scaleX": 0.0,
            "scaleY": 0.0
        },
        "attributes": {
            "x1": "-2.425",
            "y1": "22.527",
            "x2": "-3.858",
            "y2": "22.527",
            "stroke-width": "0.1"
        },
        "startPoint": {
            "x": -2.425,
            "y": 22.527
        },
        "endPoint": {
            "x": -3.858,
            "y": 22.527
        }
    }],
    "transform": {
        "rotationAngle": 0.0,
        "rotationCenter": null,
        "translate": null,
        "scaleX": 0.0,
        "scaleY": 0.0
    },
    "attributes": {
        "fill": "black"
    },
    "entityType": 10
}

С точки зрения архитектуры, даже если я осознаю, Angular не является выделенной платформой Для рендеринга графики c в браузере, есть ли у вас какие-то архитектурные хитрости или предложения для решения этой проблемы?

Спасибо,

Ответы [ 2 ]

0 голосов
/ 04 февраля 2020

вы можете попробовать использовать директиву trackBy, посмотрите здесь: https://blog.bitsrc.io/angular-optimization-use-trackby-option-for-ngfor-directive-72c9509b2be9

0 голосов
/ 04 февраля 2020

Возможно, вам следует каким-то образом попытаться его кэшировать - например, использовать подкачку страниц (не уверен, что я полностью понимаю необходимость, но кажется разумным, что вам не нужно одновременно просматривать 800+ визуальных объектов).

Мое предложение заключается в том, чтобы по возможности лениво загружать (загружать X элементов одновременно) или загружать все, кроме отображения X одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...