Performance challenges with rendering SVG in ngFor due to the presence of a highly nested array structure - in

I'm currently developing a business application that requires me to dynamically render SVG images for displaying floor plans. The SVG elements are stored in a database and provided to the front-end in JSON format, allowing the graphics to be rendered using templates.

Instead of using <img> tags, I need to be able to dynamically change attributes like viewBox and transform properties.

One architectural concern I have is the process of fetching large arrays (thousands of rows) from the backend, pre-processing them, and parsing them into JavaScript objects suitable for my components. The arrays are relatively shallow, with the deepest level of sub-arrays being just one.

The template structure is quite simple – it involves using a first ngFor loop to create <g> elements, followed by looping over nested objects that describe other SVG entities such as circles, paths, and texts.

In my current setup, the initial ngFor loop iterates through 800 objects, with subsequent loops processing between 1 to 5 objects each.

Unfortunately, the rendering process is quite slow, taking approximately 8 seconds to load. The issue lies in the need to reconstruct the SVG on the front-end, despite utilizing <defs> and <use> elements to optimize performance.

Below is a snippet from the template:

<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" />

        <!-- Additional entity types -->

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

Here is an example dataset entry representing a group with the ID "42". While this specific group contains only one SVG entity, the actual dataset could have several entities within each group:

{
    "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
}

Considering that Angular is not primarily focused on graphic rendering in browsers, do you have any architectural suggestions or tricks to enhance performance in this scenario?

Thank you!

Answer №1

One potential solution could be to implement caching, such as utilizing paging to prevent the need to view all 800+ visual objects simultaneously.

Consider implementing lazy loading by loading a certain number of items at a time, or loading all items but only displaying a set number at once.

Answer №2

If you're looking to optimize your Angular application, consider implementing the trackBy directive. Check out this resource for more information:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

CORS policy is preventing a patch request in loopback 4 from going through

Whenever I attempt to send a patch request to my API using Loopback 4, I encounter an error. All other requests work perfectly fine except for the patch request. The error message states: Access to XMLHttpRequest at 'api url' from origin ' ...

Aligning text with a scalable vector graphic (SVG) illustration

Is there a way to position the text next to the SVG object? The current output is as follows: The desired outcome is to have the text displayed alongside the SVG image: Below is the HTML code snippet: <div class="alert alert-success smallFont" id="i ...

When a TypeScript merged declaration composition is used with an extended target class, it fails to work properly

I have a TypeScript problem where I need to combine a class that has been extended with a few others. While searching for solutions, I came across an article outlining a pattern that I thought could be helpful: https://www.typescriptlang.org/docs/handbook ...

Dealing with a nested object problem in Angular using TypeScript

I am currently working on an Angular 15 application that is designed to showcase information about different games to users. Within the application, I have a global object structured like this: GAMES_INFO: { skyroads: { name: 'Sky Roads&a ...

Determine whether there is greater available space above or below a specific element within the DOM

I'm looking to create a dynamic layout where an input field is accompanied by a list in a div, positioned either above or below depending on available space. This setup needs to account for the fact that the input field could be located anywhere on th ...

ng2-select2 prevent selection of initial value

My Angular project has the following setup: Hello.component.html <select2 ngDefaultControl [data]="list" [options]="{ placeholder: placeholder }" > </select2> Hello.component.ts list = [ { id: 1, text: 'Item 1 one' }, { i ...

Retrieve the output of the subscribe function in Angular 8 service

I have a service with a method that retrieves the profile image of a user. users.service.ts getPictureProfile() { const headers = new HttpHeaders({ . . .}); const options = { headers }; const body = {...}; return this.http.post(environmen ...

Angular2: Is unsubscribing from host listeners necessary? How do host listeners function? If I don't need to unsubscribe, under what circumstances are they automatically unsubscribed?

@HostListener('window:scroll', ['$event']) onScroll(event) { // Handling scroll event } I have implemented a 'onScroll' function to listen for scroll events in various components. I haven't included an unsubscrib ...

Is it possible in Typescript to assign a type to a variable using a constant declaration?

My desired outcome (This does not conform to TS rules) : const type1 = "number"; let myVariable1 : typeof<type1> = 12; let type2 = "string" as const; let myVariable2 : typeof<type2> = "foo"; Is it possible to impl ...

Next.js routes taking precedence over storybook routes

I recently completed a storybook project. Now, I am looking to integrate it with another project built on next.js. The issue is that Storybook and next.js each have their own set of routes. I want to streamline the routing process by utilizing next.js and ...

Angular project encounters error message: 'JQuery<HTMLElement>' type does not have property 'bxSlider'

I'm encountering an issue with an Angular project where I'm attempting to utilize bxSlider. After following the installation instructions from the official website , it seems that either VS Code or Angular is not recognizing the plugin. For inst ...

Sharing information between different pages in NEXT.js version 14

After performing a fetch and receiving a successful response containing data as an object, I use router.push to redirect the page to another one where I want to display the fetched data. const handleSubmit = async (event: any) => { event.preventDefa ...

Deciphering Route Parameters within Angular 2

Recently diving into Angular 2, I stumbled upon this resource, which details various methods for creating route links. 1. <a [routerLink]="[ '/path', routeParam ]"> 2. <a [routerLink]="[ '/path', { matrixParam: 'value&ap ...

Assign a function in one class to be equivalent to a function in a different class

What is causing this issue and how should it be resolved? class A { constructor() { console.log('constructin A') } public someMethod = (x: string) => { console.log(x) } } class B { private myA: A constructor ...

Discover the seamless transformation of a class definition into a Vue 3 component definition utilizing the dazzling 'tc39' decorators

The proposed API in the tc39/proposal-decorators repository is significantly different from the previous decorators API. Although TypeScript 5 doesn't fully support the new API yet, it's only a matter of time before the old API becomes deprecated ...

Angular 2 date validation rule for dd/mm/yyyy format in forms with reactive functionality

this.seedFundForm = this.fb.group({ multipleSource: this.fb.array([]), amount:[data.amount, Validators.compose([Validators.required, Validators.pattern('[0-9]*'), Validators.maxLength(10)])], date:[data.date, Validators.compose([Valid ...

Using Angular, you can effortlessly inject elements into the editable div from any location on the page

Currently, I am working on developing an HTML interface that allows users to input text and send it as a notification to our mobile application. However, I am encountering challenges with the text and dynamically inserted elements using Angular 5; The te ...

Moving SVG Module

My goal is to create a custom component that can dynamically load and display the content of an SVG file in its template. So far, I have attempted the following approach: icon.component.ts ... @Component({ selector: 'app-icon', templa ...

Arrange an array of integers and letters alphabetically in an Angular/Typescript environment

My Sorting Strategy I am attempting to organize an array in the following manner... 1 2 2(a) 2(b) 2(b) #AsimpleName 2(b) #NameWithN 3 4 4(a) ... ... using Angular 2. Snippet of My Code Component this.streetDetailRef = this.afDatabase.list('data/us ...

Choosing the right ID in material-ui styles/JSS: A guide

In my React application, I am utilizing @material-ui/styles for styling, which is built on JSS. I am currently using the higher-order component API for styling purposes. My question is, how can I target an element by its id in my styles? Despite searchin ...