Skip to content

Commit

Permalink
Merge pull request #37 from MarshMapper/add-layer-list
Browse files Browse the repository at this point in the history
Add Layer control panel to adjust opacity and visibility of individua…
  • Loading branch information
MarshMapper authored Aug 18, 2024
2 parents 19948c3 + 7682a9a commit 20083be
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 26 deletions.
8 changes: 6 additions & 2 deletions src/app/components/arc-map/arc-map.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@
<mat-tab-group preserveContent>
<mat-tab class="tab-content" label="Places">
<ng-template matTabContent>
<app-feature-list [featureLayerView$]="protectedLayerViewSubject"></app-feature-list>
<app-feature-list [featureLayerView$]="protectedLayerViewSubject.asObservable()"></app-feature-list>
</ng-template>
</mat-tab>
<mat-tab class="tab-content" label="Layers">
<ng-template matTabContent>
<app-layer-control-panel [overlayLayers$]="overlayLayersSubject.asObservable()"></app-layer-control-panel>
</ng-template>
</mat-tab>
<mat-tab class="tab-content" label="Layers"> </mat-tab>
</mat-tab-group>
</div>
}
Expand Down
9 changes: 7 additions & 2 deletions src/app/components/arc-map/arc-map.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import { whenOnce } from '@arcgis/core/core/reactiveUtils';
import { NjHistoricalMapsService, NjHistoricalMapType } from '../../services/nj-historical-maps.service';
import Layer from '@arcgis/core/layers/Layer';
import { FeatureListComponent } from "../feature-list/feature-list.component";
import { Subject } from 'rxjs';
import { BehaviorSubject, Subject } from 'rxjs';
import { LayerControlPanelComponent } from "../layer-control-panel/layer-control-panel.component";

@Component({
selector: 'app-arc-map',
standalone: true,
imports: [CommonModule, ComponentLibraryModule, CalciteComponentsModule, MatTabsModule, FeatureListComponent],
imports: [CommonModule, ComponentLibraryModule, CalciteComponentsModule, MatTabsModule, FeatureListComponent, LayerControlPanelComponent],

templateUrl: './arc-map.component.html',
styleUrl: './arc-map.component.scss'
Expand All @@ -36,6 +37,7 @@ export class ArcMapComponent implements OnInit {
public isSmallPortrait: boolean = false;
private breakpointObserver = inject(BreakpointObserver);
public protectedLayerViewSubject: Subject<__esri.FeatureLayerView> = new Subject<__esri.FeatureLayerView>();
public overlayLayersSubject: BehaviorSubject<Layer[]> = new BehaviorSubject<Layer[]>([]);

isSmallPortrait$ = this.breakpointObserver.observe([
Breakpoints.TabletPortrait,
Expand All @@ -56,6 +58,7 @@ export class ArcMapComponent implements OnInit {
const view: View = event.target.view;
const unprotectedAreasLayer: ImageryTileLayer = this.unprotectedAreasService.createImageryTileLayer();
const protectedAreasLayer: FeatureLayer = this.protectedAreasService.createFeatureLayer();
let overlayLayers: Layer[] = [protectedAreasLayer, unprotectedAreasLayer];

map.add(unprotectedAreasLayer);
this.unprotectedAreasService.initializePopup(view);
Expand All @@ -68,8 +71,10 @@ export class ArcMapComponent implements OnInit {
const historicalLayer: Layer | undefined = this.njHistoricalMapsService.createLayer(<NjHistoricalMapType>mapType);
if (historicalLayer) {
map.add(historicalLayer);
overlayLayers.push(historicalLayer);
}
});
this.overlayLayersSubject.next(overlayLayers);
this.waitForLayersToLoad(view, map, unprotectedAreasLayer, protectedAreasLayer);
}
waitForLayersToLoad(view: View, map: Map, unprotectedAreasLayer: ImageryTileLayer, protectedAreasLayer: FeatureLayer): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div [ngClass]="getLayerContainerClass()">
@for(layer of overlayLayers$ | async; track layer.id) {
<div class="layer-container" >
<span class="layer-title">{{layer.title}}</span>
<div class="slider-container">
<mat-slide-toggle [checked]="layer.visible" (change)="toggleLayerVisibility(layer)">
{{layer.visible ? 'Visible' : 'Not Visible'}}
</mat-slide-toggle>
<mat-slider min="0" max="1" step="0.05" [displayWith]="getSliderLabel">
<input matSliderThumb #opacitySlider value="{{layer.opacity}}" (valueChange)="opacityChanged(layer, $event)" />
</mat-slider>
<span>Opacity: {{opacitySlider.value}}</span>
</div>
</div>
}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.layer-title {
font-size: 14px;
font-weight: 700;
}
.layer-container {
margin: 10px;
padding: 10px;
font-size: 13px;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2);
}
.slider-container {
margin: 0px;
padding: 6px;
display: grid;
grid-template-columns: 30% 45% 25%;
align-items: center;
}
.layer-container-horizontal {
height: calc(100vh - 112px);
overflow-y: auto;
}
.layer-container-vertical {
height: calc(40vh - 48px);
overflow-y: auto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { LayerControlPanelComponent } from './layer-control-panel.component';

describe('LayerControlPanelComponent', () => {
let component: LayerControlPanelComponent;
let fixture: ComponentFixture<LayerControlPanelComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LayerControlPanelComponent]
})
.compileComponents();

fixture = TestBed.createComponent(LayerControlPanelComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Component, inject, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import Layer from '@arcgis/core/layers/Layer';
import { map, Observable, shareReplay } from 'rxjs';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSliderModule } from '@angular/material/slider';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';

@Component({
selector: 'app-layer-control-panel',
standalone: true,
imports: [CommonModule, MatSlideToggleModule, MatSliderModule],
templateUrl: './layer-control-panel.component.html',
styleUrl: './layer-control-panel.component.scss'
})
export class LayerControlPanelComponent implements OnInit {
@Input() overlayLayers$!: Observable<Layer[]>;
public isSmallPortrait: boolean = false;
private breakpointObserver = inject(BreakpointObserver);
isSmallPortrait$ = this.breakpointObserver.observe([
Breakpoints.TabletPortrait,
Breakpoints.HandsetPortrait])
.pipe(
map(result => result.matches),
shareReplay()
);
ngOnInit(): void {
this.isSmallPortrait$.subscribe((isSmallPortrait) => {
this.isSmallPortrait = isSmallPortrait;
});
}
toggleLayerVisibility(layer: Layer) {
layer.visible = !layer.visible;
}
opacityChanged(layer: Layer, event: number) {
layer.opacity = event;
}
getSliderLabel(value: number): string {
return '' + Math.round(value * 100) / 100;
}
getLayerContainerClass(): string {
return this.isSmallPortrait ? 'layer-container-vertical' : 'layer-container-horizontal';
}
}
44 changes: 22 additions & 22 deletions src/app/services/nj-historical-maps.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import WMSLayer from '@arcgis/core/layers/WMSLayer';

export enum NjHistoricalMapType {
HistoricalMaps1881to1924,
LandCover2007,
LandCover2020,
AerialImagery1930,
WetlandsImagery1970,
UsgsTopo100k,
WetlandsFromLandCover2002,
WetlandsImagery1970,
AerialImagery1930,
LandCover2007,
LandCover2020,
}
export enum LayerType {
WMSLayer,
Expand Down Expand Up @@ -41,6 +41,24 @@ export class NjHistoricalMapsService {
url: "https://img.nj.gov/imagerywms/HistoricalMaps",
layerType: LayerType.WMSLayer
},
{
type: NjHistoricalMapType.WetlandsImagery1970,
title: "Wetlands Imagery (1970)",
url: "https://img.nj.gov/imagerywms/Wetlands1970",
layerType: LayerType.WMSLayer,
},
{
type: NjHistoricalMapType.AerialImagery1930,
title: "Aerial Imagery (1930)",
url: "https://img.nj.gov/imagerywms/BlackWhite1930",
layerType: LayerType.WMSLayer
},
{
type: NjHistoricalMapType.UsgsTopo100k,
title: "USGS Topo 100k",
url: "https://img.nj.gov/imagerywms/Topo100K",
layerType: LayerType.WMSLayer
},
{
type: NjHistoricalMapType.LandCover2007,
title: "NJ Land Cover (2007)",
Expand All @@ -53,30 +71,12 @@ export class NjHistoricalMapsService {
url: "https://services1.arcgis.com/QWdNfRs7lkPq4g4Q/arcgis/rest/services/Land_Use_2020/FeatureServer/5",
layerType: LayerType.FeatureLayer,
},
{
type: NjHistoricalMapType.UsgsTopo100k,
title: "USGS Topo 100k",
url: "https://img.nj.gov/imagerywms/Topo100K",
layerType: LayerType.WMSLayer
},
{
type: NjHistoricalMapType.WetlandsFromLandCover2002,
title: "Wetlands from Land Cover (2002)",
url: "https://mapsdep.nj.gov/arcgis/rest/services/Features/Land_lu/MapServer/9",
layerType: LayerType.FeatureLayer,
},
{
type: NjHistoricalMapType.WetlandsImagery1970,
title: "Wetlands Imagery (1970)",
url: "https://img.nj.gov/imagerywms/Wetlands1970",
layerType: LayerType.WMSLayer,
},
{
type: NjHistoricalMapType.AerialImagery1930,
title: "Aerial Imagery (1930)",
url: "https://img.nj.gov/imagerywms/BlackWhite1930",
layerType: LayerType.WMSLayer
}
];
constructor() { }

Expand Down

0 comments on commit 20083be

Please sign in to comment.