Say you have an app like Uber, and you want to place the recorded route on the map. You have 3 different types of feature map components that display a route.
Will you add the same map children over and over in each feature map component? What happens if you need to change the way you render the route? Will you change it in all components? 🤔
You could instead, create a feature child component or directive which will:
It would be great if we could centralize and encapsulate route rendering somehow, then reuse it inside the different map types we have, so it is scalable. Something like:
<bs-google-map *bsSafe>
<app-route-overlay [ride]="ride"></app-route-overlay>
<bs-google-map>
I'm interested in a Template driven solution | Programmatic solution.
We'll create a component and place all overlay directives necessary for our route rendering in its template:
// route-overlay.component.ts
@Component({
selector : 'app-route-overlay',
templateUrl: './route-overlay.component.html',
styleUrls : ['./route-overlay.component.css']
})
export class RouteOverlayComponent
{
@Input public ride: Ride;
// Additional implementation ...
}
<!-- route-overlay.component.html -->
<bs-google-maps-marker #start [position]="ride.start.position" [icon]="YOUR_START_ICON"></bs-google-maps-marker>
<bs-google-maps-marker #end [position]="ride.end.position" [icon]="YOUR_END_ICON"></bs-google-maps-marker>
<bs-google-maps-polyline [path]="ride.route"></bs-google-maps-polyline>
<bs-google-maps-info [attachedTo]="start">{{route.start.time}}</bs-google-maps-info>
<bs-google-maps-info [attachedTo]="end" >{{route.end.time}}</bs-google-maps-info>
We'll create a directive and inject it with its parent map component, then fetch the overlays superpower and use it to add the overlays:
// route-overlay.directive.ts
@Directive({
selector: 'app-route-overlay',
exportAs: 'routeOverlay'
})
export class RouteOverlayDirective
{
@Input public ride: Ride;
private map: GoogleMap;
// Inject the parent map component
constructor(private mapComponent: GoogleMapComponent)
{
// Extract the map
this.map = this.mapComponent.wrapper;
}
ngOnInit()
{
this.addOverlays();
}
public addOverlays(): void
{
// Get a hold of the map and extract the overlays superpower
const overlays = this.map.superpowers.use(OverlaysSuperpower);
const start = overlays.createMarker(ride.start.position, { icon: YOUR_START_ICON });
const end = overlays.createMarker(ride.end.position, { icon: YOUR_END_ICON });
overlays.createPolyline(ride.path);
overlays.createInfoWindow(start, ride.start.time);
overlays.createInfoWindow(end, ride.end.time);
}
}
Tip: Design your
@Input
properties to receive the entire data structure (e.g. an entity, or a model) they are intended for. Model changes will require zero-to-minimal effort as you will only have to adapt the component and not the using code.
Topic | Description |
---|---|
Feature Maps | Best practices for maps scalability. |