Hi,
in the past I was able to create a CustomElevationLayer with Exaggeration for an Esri Javascript 3D scene:
Custom Elevation Layer with Exaggeration
Now I would like ro realize the same task with Typescript. The general patterns to use Esri API in Typescript are clear but I'm struggling when it comes to:
BaseElevationLayer.createSubclass({...})
TypeScript compiler tells me that Property 'createSubclass' does not exist on type 'BaseElevationLayerConstructor' and I can see this clearly in the TypeDefinitions. This method appears nowhere.
So how can I create a custom ElevationLayer in Typescript?
Does anybody has an idea?
Solved! Go to Solution.
I`ve been able to solve this on my own and I want to share my solution here. Probably it`s not the best one, so I`m open for improvements.
import { subclass, declared, property } from 'esri/core/accessorSupport/decorators';
@subclass('hwrm.ExagerratedElevationLayer')
export class ExaggeratedElevationLayer extends declared(BaseElevationLayer) {
private _elevationLayer: ElevationLayer;
private _spatialReference: SpatialReference;
private _tileInfo: TileInfo;
private _fullExtent: Extent;
private _exaggeration: number;
private _elevationServiceURL: string;
@property()
get elevationLayer(): ElevationLayer {
return this._elevationLayer;
};
set elevationLayer(value: ElevationLayer) {
const oldValue = this._get < ElevationLayer > ("elevationLayer");
if (oldValue !== value) {
this._set("elevationLayer", value);
}
};
@property()
get spatialReference(): SpatialReference {
return this._spatialReference;
};
set spatialReference(value: SpatialReference) {
const oldValue = this._get < SpatialReference > ("spatialReference");
if (oldValue !== value) {
this._set("spatialReference", value);
}
};
@property()
get tileInfo(): TileInfo {
return this._tileInfo;
};
set tileInfo(value: TileInfo) {
const oldValue = this._get < TileInfo > ("tileInfo");
if (oldValue !== value) {
this._set("tileInfo", value);
}
};
@property()
get fullExtent(): Extent {
return this._fullExtent;
};
set fullExtent(value: Extent) {
const oldValue = this._get < Extent > ("fullExtent");
if (oldValue !== value) {
this._set("fullExtent", value);
}
};
@property()
get exaggeration(): number {
return this._exaggeration;
};
set exaggeration(value: number) {
const oldValue = this._get < number > ("exaggeration");
if (oldValue !== value) {
this._set("exaggeration", value);
}
};
@property()
get elevationServiceURL(): string {
return this._elevationServiceURL;
};
set elevationServiceURL(value: string) {
const oldValue = this._get < string > ("elevationServiceURL");
if (oldValue !== value) {
this._set("elevationServiceURL", value);
}
};
load(): IPromise < any > {
let elevationLayer: ElevationLayer = new ElevationLayer({
url: this._get < string > ("elevationServiceURL")
});
this._set("elevationLayer", elevationLayer);
return this.addResolvingPromise(this._get < ElevationLayer > ("elevationLayer").load());
};
fetchTile(level: number, row: number, col: number) {
return this._get < ElevationLayer > ("elevationLayer").fetchTile(level, row, col)
.then(function(data) {
data.values.forEach(function(value: number, index: number, values: number[]) {
console.log(this);
values[index] = value * this._get < number > ("exaggeration");
}.bind(this));
return data;
}.bind(this));
};
}
I consumed my extended class like so:
let exaggeratedElevationLayer: HwrmLayers.HwrmLayers.ExaggeratedElevationLayer = new HwrmLayers.HwrmLayers.ExaggeratedElevationLayer();
exaggeratedElevationLayer.elevationServiceURL = this._config.elevationServiceURL;
exaggeratedElevationLayer.exaggeration = 10;
exaggeratedElevationLayer.fullExtent = this._fullExtent;
exaggeratedElevationLayer.tileInfo = this._tileInfo;
exaggeratedElevationLayer.spatialReference = this._tileInfo.spatialReference;
this._map.ground.layers.add(exaggeratedElevationLayer);
The 2 HwrmLayers in front derive from my individual code structure with import alias and namespace.
I`ve been able to solve this on my own and I want to share my solution here. Probably it`s not the best one, so I`m open for improvements.
import { subclass, declared, property } from 'esri/core/accessorSupport/decorators';
@subclass('hwrm.ExagerratedElevationLayer')
export class ExaggeratedElevationLayer extends declared(BaseElevationLayer) {
private _elevationLayer: ElevationLayer;
private _spatialReference: SpatialReference;
private _tileInfo: TileInfo;
private _fullExtent: Extent;
private _exaggeration: number;
private _elevationServiceURL: string;
@property()
get elevationLayer(): ElevationLayer {
return this._elevationLayer;
};
set elevationLayer(value: ElevationLayer) {
const oldValue = this._get < ElevationLayer > ("elevationLayer");
if (oldValue !== value) {
this._set("elevationLayer", value);
}
};
@property()
get spatialReference(): SpatialReference {
return this._spatialReference;
};
set spatialReference(value: SpatialReference) {
const oldValue = this._get < SpatialReference > ("spatialReference");
if (oldValue !== value) {
this._set("spatialReference", value);
}
};
@property()
get tileInfo(): TileInfo {
return this._tileInfo;
};
set tileInfo(value: TileInfo) {
const oldValue = this._get < TileInfo > ("tileInfo");
if (oldValue !== value) {
this._set("tileInfo", value);
}
};
@property()
get fullExtent(): Extent {
return this._fullExtent;
};
set fullExtent(value: Extent) {
const oldValue = this._get < Extent > ("fullExtent");
if (oldValue !== value) {
this._set("fullExtent", value);
}
};
@property()
get exaggeration(): number {
return this._exaggeration;
};
set exaggeration(value: number) {
const oldValue = this._get < number > ("exaggeration");
if (oldValue !== value) {
this._set("exaggeration", value);
}
};
@property()
get elevationServiceURL(): string {
return this._elevationServiceURL;
};
set elevationServiceURL(value: string) {
const oldValue = this._get < string > ("elevationServiceURL");
if (oldValue !== value) {
this._set("elevationServiceURL", value);
}
};
load(): IPromise < any > {
let elevationLayer: ElevationLayer = new ElevationLayer({
url: this._get < string > ("elevationServiceURL")
});
this._set("elevationLayer", elevationLayer);
return this.addResolvingPromise(this._get < ElevationLayer > ("elevationLayer").load());
};
fetchTile(level: number, row: number, col: number) {
return this._get < ElevationLayer > ("elevationLayer").fetchTile(level, row, col)
.then(function(data) {
data.values.forEach(function(value: number, index: number, values: number[]) {
console.log(this);
values[index] = value * this._get < number > ("exaggeration");
}.bind(this));
return data;
}.bind(this));
};
}
I consumed my extended class like so:
let exaggeratedElevationLayer: HwrmLayers.HwrmLayers.ExaggeratedElevationLayer = new HwrmLayers.HwrmLayers.ExaggeratedElevationLayer();
exaggeratedElevationLayer.elevationServiceURL = this._config.elevationServiceURL;
exaggeratedElevationLayer.exaggeration = 10;
exaggeratedElevationLayer.fullExtent = this._fullExtent;
exaggeratedElevationLayer.tileInfo = this._tileInfo;
exaggeratedElevationLayer.spatialReference = this._tileInfo.spatialReference;
this._map.ground.layers.add(exaggeratedElevationLayer);
The 2 HwrmLayers in front derive from my individual code structure with import alias and namespace.