During the process of replacing an existing flash application which rendered 2D truck graphics to a webpage, we were asked the question of how to adopt this functionality into an Angular 6 application. Additional requirements were the full scalability and the dynamic adaption of the graphic due to user inputs. Based on our research Scalable Vector Graphics (SVG) are the best choice to match these requirements. In the following, we will provide an insight of what you should keep in mind if you are dealing with SVG and how to use them in an Angular 6 application.
SVG in Angular
Scalable Vector Graphics are basically a specification for describing 2D vector graphics like rectangles circles or paths. Due to the fact that SVG are an XML based markup language, the integration into an Angular 6 application is pretty straightforward. Angular provides a lot of features for markups like data and event bindings, components and directives and moreover animations. Furthermore, it is possible to manipulate SVG elements via Typescript and CSS. As the full scalability is in the nature of SVG, there is no need to care about this requirement.
Due to the fact that SVG are a markup like HTML you can embed SVG by simply locating them into an HTML template. The graphic below represents a simplified prototype of a truck SVG, which we will use in a revised version in our application. To reduce the complexity of the following we will just deal with one stabilizer. Consider the stabilizer as part of the entire SVG, then you will find six simple shapes as shown below.
Rendering static content is fine but as we need to adapt the graphic dynamically based on user inputs there has to be a way to set up dynamic bindings in the view. As there are attributes but no appropriate properties on the DOM of an SVG element, we have to tell Angular to set attributes instead of properties. Therefore the typical Angular way for dynamic bindings like [x]=”xValue” won´t work, instead the attr. prefix like [attr.x]=”xValue” must be used. In our example, we created a variable “stab” inside the “.ts” file which holds all attributes we want to dynamically bind to the view.
Creating separate components
For simple SVG it is adequate to keep the markup directly in the template, but as the SVG increase in size and complexity it helps to separate and reuse several components to make it clearer and more structured. The typical Angular approach would be to shift the code into a separate component and insert the custom element at any place you want to use it. If we are only dealing with HTML it works out perfectly but as SVG are XML the browser is not able to render custom elements which are unknown XML elements at that time.
A way to fix it is to take a closer look at the component metadata’s selector property and add an attribute selector like “[stabilizer]” instead of an element selector “stabilizer”. Now the component will be attached to any element which has the attribute “stabilizer” as shown below:
The stabilizer component is now separated from the truck SVG and can be modified according to specific needs. In this case with a simple group for length specification which adapts due to the stabilizer itself.
You may have noticed the “svg:” namespace prefix. If the SVG content stays in the same component as the “<svg>” root tag the prefix is not needed because Angular will infer the correct namespace by default. Contrary, if the component is split up it will no longer work and the prefix has to be set manually. Now it is possible to manipulate the separated stabilizer component in all possible ways as shown below.
If you pay attention to these simple rules dealing with SVG in an Angular 6 application is pretty straightforward.
- For dynamic bindings use the “attr.” prefix to bind attributes instead of properties
- For separating components use attribute selectors “selector: ‘[stabilizer]'” instead of element selectors and apply them: “<g stabilizer></g>”
- If the SVG content is not included in the same component as the root “<svg>” tag use the “svg:” prefix on each element to tell Angular that it is an SVG.
Due to the fact that you can simply drop SVG into an Angular template, the easy access and manipulation of elements via Typescript and CSS and the features which Angular provides for markup, it almost seems that SVG were made to be used within an Angular application. Although there are other rendering pipelines like Canvas or HTML which have distinct advantages, SVG is the perfect fit for our use case.