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!