Phase F: Add SVG interactivity with event binding for country selection
This commit is contained in:
22
src/app/map-svg/map-svg.css
Normal file
22
src/app/map-svg/map-svg.css
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
.svg-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep svg {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .country-path {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: fill 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host ::ng-deep .country-path:hover {
|
||||||
|
fill: #3498db !important;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
1
src/app/map-svg/map-svg.html
Normal file
1
src/app/map-svg/map-svg.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<div class="svg-container"></div>
|
||||||
51
src/app/map-svg/map-svg.ts
Normal file
51
src/app/map-svg/map-svg.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { Component, Output, EventEmitter, AfterViewInit, ElementRef } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-map-svg',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './map-svg.html',
|
||||||
|
styleUrl: './map-svg.css'
|
||||||
|
})
|
||||||
|
export class MapSvgComponent implements AfterViewInit {
|
||||||
|
@Output() countryClick = new EventEmitter<string>();
|
||||||
|
|
||||||
|
constructor(private http: HttpClient, private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
// Load SVG file and inject it into the component
|
||||||
|
this.http.get('assets/map-image.svg', { responseType: 'text' }).subscribe({
|
||||||
|
next: (svgContent) => {
|
||||||
|
const container = this.elementRef.nativeElement.querySelector('.svg-container');
|
||||||
|
if (container) {
|
||||||
|
container.innerHTML = svgContent;
|
||||||
|
this.attachClickHandlers();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
console.error('Failed to load SVG:', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private attachClickHandlers(): void {
|
||||||
|
const svgElement = this.elementRef.nativeElement.querySelector('svg');
|
||||||
|
if (!svgElement) return;
|
||||||
|
|
||||||
|
// Find all path elements with id attributes (country codes)
|
||||||
|
const paths = svgElement.querySelectorAll('path[id]');
|
||||||
|
|
||||||
|
paths.forEach((path: Element) => {
|
||||||
|
const countryCode = path.getAttribute('id');
|
||||||
|
if (countryCode) {
|
||||||
|
// Add hover effect
|
||||||
|
path.setAttribute('class', 'country-path');
|
||||||
|
|
||||||
|
// Add click handler
|
||||||
|
path.addEventListener('click', () => {
|
||||||
|
this.countryClick.emit(countryCode.toUpperCase());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="map-column">
|
<div class="map-column">
|
||||||
<h2>Interactive World Map</h2>
|
<h2>Interactive World Map</h2>
|
||||||
<div class="map-container">
|
<div class="map-container">
|
||||||
<img src="assets/map-image.svg" alt="World Map" class="world-map" />
|
<app-map-svg (countryClick)="onCountrySelected($event)"></app-map-svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { WorldBankService, CountryData } from '../services/world-bank';
|
import { WorldBankService, CountryData } from '../services/world-bank';
|
||||||
|
import { MapSvgComponent } from '../map-svg/map-svg';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-map',
|
selector: 'app-map',
|
||||||
imports: [CommonModule],
|
imports: [CommonModule, MapSvgComponent],
|
||||||
templateUrl: './map.html',
|
templateUrl: './map.html',
|
||||||
styleUrl: './map.css'
|
styleUrl: './map.css'
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user