#angular #arcgis #arcgis-js-api #angular10 #esri-loader
#angular #arcgis #arcgis-js-api #angular10 #esri-загрузчик
Вопрос:
Как использовать ‘geographicToWebMercator’ в Angular 10, чтобы нарисовать полигон со значениями колец. Я имею в виду пример, приведенный в документации,https://developers.arcgis.com/documentation/core-concepts/features-and-geometries/#polygons и пытаюсь использовать функциональные возможности Angular с ArcGIS esri-loader. Вот документация, на которую я ссылаюсь. https://developers.arcgis.com/javascript/latest/guide/angular /
Я попытался получить точки проектируемого полигона. Но возвращает неправильные значения.
import {
Component,
OnInit,
ViewChild,
ElementRef,
Input,
Output,
EventEmitter,
OnDestroy,
} from '@angular/core';
import { loadModules } from 'esri-loader';
import esri = __esri; // Esri TypeScript Types
import { empty } from 'rxjs';
@Component({
selector: 'app-esri-map',
templateUrl: './esri-map.component.html',
styleUrls: ['./esri-map.component.css'],
})
export class EsriMapComponent implements OnInit, OnDestroy {
@Output() mapLoadedEvent = new EventEmitter<boolean>();
@ViewChild('mapViewNode', { static: true }) private mapViewEl: ElementRef;
/**
* _zoom sets map zoom
* _center sets map center
* _basemap sets type of map
* _loaded provides map loaded status
*/
private _zoom = 20;
private _basemap = 'hybrid';
private _loaded = false;
private _view: esri.MapView = null;
private _nextBasemap = 'streets';
get mapLoaded(): boolean {
return this._loaded;
}
@Input()
set zoom(zoom: number) {
this._zoom = zoom;
}
get zoom(): number {
return this._zoom;
}
@Input()
set basemap(basemap: string) {
this._basemap = basemap;
}
get basemap(): string {
return this._basemap;
}
@Input()
set nextBasemap(nextBasemap: string) {
this._nextBasemap = nextBasemap;
}
get nextBasemap(): string {
return this._nextBasemap;
}
constructor() {}
async getProjectedpolygon(params: any) {
const [GeometryService] = await loadModules(['esri/tasks/GeometryService']);
console.log(`input polygon: ${JSON.stringify(params.toJSON())}`);
const geomSer = new GeometryService(
'http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer'
);
geomSer.project(params).then(function (result) {
const projectedPoly = result[0];
if (!projectedPoly) {
return;
}
console.log(
`Projected Polygon: ${JSON.stringify(projectedPoly.toJSON())}`
);
// return projectedPoly;
});
}
async initializeMap() {
try {
// Load the modules for the ArcGIS API for JavaScript
const [
EsriMap,
EsriMapView,
FeatureLayer,
BasemapToggle,
BasemapGallery,
webMercatorUtils,
Polygon,
Graphic,
SimpleFillSymbol,
GeometryService,
ProjectParameters,
SpatialReference,
] = await loadModules([
'esri/Map',
'esri/views/MapView',
'esri/layers/FeatureLayer',
'esri/widgets/BasemapToggle',
'esri/widgets/BasemapGallery',
'esri/geometry/support/webMercatorUtils',
'esri/geometry/Polygon',
'esri/Graphic',
'esri/symbols/SimpleFillSymbol',
'esri/tasks/GeometryService',
'esri/tasks/support/ProjectParameters',
'esri/geometry/SpatialReference',
]);
const poly = Polygon.fromJSON({
rings: [
[
[2755899.9999897182, 542357.7692040652],
[2755880.0069194734, 542356.78593830764],
[2755881.7250918895, 542323.36310489476],
[2755825.535899803, 542319.92347922921],
[2755846.6395321339, 541826.4208573103],
[2755848.0673508048, 541783.2063768059],
[2755849.6063897163, 541736.63199488819],
[2755853.2533640563, 541637.62366272509],
[2755853.747457549, 541624.21063180268],
[2755844.9098768085, 541604.88324263692],
[2755840.0076556355, 541604.63127464056],
[2755840.858703807, 541584.26386131346],
[2755696.7467873096, 541576.85377115011],
[2755695.3304515481, 541630.02623698115],
[2755695.2727088928, 541632.78771439195],
[2755693.2822273076, 541727.9331934005],
[2755692.2743553072, 541778.09352613986],
[2755691.192008391, 541827.82735055685],
[2755685.6582268029, 542074.87574097514],
[2755683.43447797, 542124.91665139794],
[2755676.4262898862, 542274.51674589515],
[2755689.3068415523, 542275.07809647918],
[2755688.1060565561, 542301.07771639526],
[2755718.8845383078, 542345.19869114459],
[2755808.4171676338, 542473.54521922767],
[2755824.3219914734, 542498.22528797388],
[2755834.2757117152, 542498.80697973073],
[2755854.8573634773, 542526.09924797714],
[2755868.594868809, 542578.80485123396],
[2755868.6171784699, 542578.83765955269],
[2755899.9999897182, 542624.7959009707],
[2755920.8641212136, 542655.35030181706],
[2756017.1844666302, 542660.17968848348],
[2756013.8029117137, 542710.30819714069],
[2756010.1959635466, 542763.77626605332],
[2755899.9999897182, 542757.74018889666],
[2755858.8612924665, 542755.48691256344],
[2755856.16346322, 542804.39462314546],
[2755899.9999897182, 542806.61312264204],
[2756006.9410488009, 542812.02584147453],
[2756021.3320961446, 542812.82603672147],
[2756073.078383714, 542815.70299947262],
[2756156.5181774646, 542820.34242589772],
[2756161.6395583004, 542717.00962731242],
[2756171.2474787235, 542523.15535622835],
[2756053.1381348819, 542512.12617881596],
[2756041.1913083941, 542508.49495247006],
[2756026.1532807201, 542503.48676039279],
[2756011.1966177225, 542498.69838413596],
[2755984.824951306, 542480.93496823311],
[2755968.4503121376, 542464.29556581378],
[2755964.7866055518, 542457.93402998149],
[2755936.9047715515, 542405.95185047388],
[2755918.0816464722, 542358.65863797069],
[2755899.9999897182, 542357.7692040652],
],
],
spatialReference: {
wkid: 102704,
},
});
const geomSer = new GeometryService(
'http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer'
);
const outSpatialReference = new SpatialReference({ wkid: 102704 });
const params = new ProjectParameters({
geometries: [poly],
outSpatialReference,
});
// let geomser = await geomSer.project(params);
let geomser = await Promise.all([this.getProjectedpolygon(params)]);
console.log(geomser);
// Configure the Map
const mapProperties: esri.MapProperties = {
basemap: this._basemap,
};
const map: esri.Map = new EsriMap(mapProperties);
// Initialize the MapView
const mapViewProperties: esri.MapViewProperties = {
container: this.mapViewEl.nativeElement,
// center: this._center,
zoom: this._zoom,
map: map,
extent: webMercatorUtils.geographicToWebMercator(
poly.extent.clone().expand(3)
),
};
this._view = new EsriMapView(mapViewProperties);
// this._view.graphics.add(graphic);
await this._view.when();
return this._view;
} catch (error) {
console.log('EsriLoader: ', error);
}
}
ngOnInit() {
this.initializeMap().then((mapView) => {
console.log('mapView ready: ', this._view.ready);
this._loaded = this._view.ready;
this.mapLoadedEvent.emit(true);
});
}
ngOnDestroy() {
if (this._view) {
this._view.container = null;
}
}
}
/Обновленный код*****/
import {
Component,
OnInit,
ViewChild,
ElementRef,
Input,
Output,
EventEmitter,
OnDestroy,
} from '@angular/core';
import { loadModules } from 'esri-loader';
import esri = __esri; // Esri TypeScript Types
import { empty } from 'rxjs';
import { __asyncValues } from 'tslib';
@Component({
selector: 'app-esri-map',
templateUrl: './esri-map.component.html',
styleUrls: ['./esri-map.component.css'],
})
export class EsriMapComponent implements OnInit, OnDestroy {
// The <div> where we will place the map
@ViewChild('mapViewNode', { static: true }) private mapViewEl: ElementRef;
// view: any;
// to keep loaded esri modules
esriModules = {
geometry: {
Polygon: null,
SpatialReference: null,
support: { webMercatorUtils: null },
},
tasks: {
GeometryService: null,
support: { ProjectParameters: null },
},
};
private _zoom = 20;
private _center: Array<number> = [-95.937187, 41.258652];
private _basemap = 'hybrid';
private _loaded = false;
private _view: esri.MapView = null;
private _nextBasemap = 'streets';
public _selectedLayer: Array<string>;
public onLayerChange(val: Array<string>) {
this._selectedLayer = val;
this.initializeMap();
}
constructor() {}
async initializeMap() {
try {
// Load the modules for the ArcGIS API for JavaScript
const [
EsriMap,
EsriMapView,
Polygon,
SpatialReference,
webMercatorUtils,
GeometryService,
ProjectParameters,
] = await loadModules([
'esri/Map',
'esri/views/MapView',
'esri/geometry/Polygon',
'esri/geometry/SpatialReference',
'esri/geometry/support/webMercatorUtils',
'esri/tasks/GeometryService',
'esri/tasks/support/ProjectParameters',
]);
// save the modules on a property for later
this.esriModules.geometry.Polygon = Polygon;
this.esriModules.geometry.SpatialReference = SpatialReference;
this.esriModules.geometry.support.webMercatorUtils = webMercatorUtils;
this.esriModules.tasks.GeometryService = GeometryService;
this.esriModules.tasks.support.ProjectParameters = ProjectParameters;
// Configure the Map
const mapProperties: esri.MapProperties = {
basemap: this._basemap,
};
const map: esri.Map = new EsriMap(mapProperties);
// Initialize the MapView
const mapViewProperties: esri.MapViewProperties = {
container: this.mapViewEl.nativeElement,
center: this._center,
zoom: this._zoom,
map: map,
};
this._view = new EsriMapView(mapViewProperties);
// const map = new Map(mapProperties);
// Initialize the MapView
// const mapViewProperties = {
// container: this.mapViewEl.nativeElement,
// map,
// };
// this.view = new MapView(mapViewProperties);
// this._view = new EsriMapView(mapViewProperties);
await this._view.when();
return this._view;
} catch (error) {
console.error('EsriLoader: ', error);
}
}
// be carefull does not handle point geometries
// point geometry extent is null
public zoomToGeometry(geom) {
console.log('in zoomToGeometry');
console.log(`Original Geometry: ${JSON.stringify(geom.toJSON())}`);
const geomSer = new this.esriModules.tasks.GeometryService(
'http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer'
);
const outSpatialReference = new this.esriModules.geometry.SpatialReference({
wkid: 102100,
});
const params = new this.esriModules.tasks.support.ProjectParameters({
geometries: [geom],
outSpatialReference,
});
geomSer.project(params).then(function (result) {
const projectedGeom = result[0];
if (!projectedGeom) {
console.log('projection geom');
return;
}
console.log(
`Projected Geometry: ${JSON.stringify(projectedGeom.toJSON())}`
);
this._view.extent = projectedGeom.extent.clone().expand(3);
});
}
ngOnInit() {
this.initializeMap();
const geom = new this.esriModules.geometry.Polygon({
spatialReference: {
wkid: 102704,
},
rings: [
[
[2744913.4668447226, 541568.06113781035],
[2744917.4038447142, 541499.65215389431],
[2744864.2454864681, 541496.82210706174],
[2744813.6648789644, 541494.12952713668],
[2744810.2104895562, 541563.64283956587],
[2744860.4905727208, 541565.79441006482],
[2744913.4668447226, 541568.06113781035],
],
],
});
this.zoomToGeometry(geom);
}
ngOnDestroy() {
if (this._view) {
// destroy the map view
this._view.container = null;
}
}
}
Комментарии:
1. У вас есть какой-то код, который в данный момент не работает? Кроме просмотра документации, что вы пробовали? 🙂
2. @erica Как можно использовать ‘extent: webMercatorUtils.geographicToWebMercator(poly.extent.expand(3))’ в angular. Я новичок в Angular. 🙂
Ответ №1:
Первое, что вам нужно сделать, это получить базовый пример совместной работы esri-loader
и angular. Если вы еще не там, загляните в документы, в разделе руководства есть пара простых примеров, с которых можно начать (ArcGIS Guide — Angular).
Теперь, когда у вас есть базовый пример, вам просто нужно загрузить webMercatorUtils
модуль и использовать его. Используя пример из ArcGIS Guide в качестве основы, вы можете сделать что-то вроде этого,
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from "@angular/core";
import { loadModules } from "esri-loader";
@Component({
selector: "app-esri-map",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class MapComponent implements OnInit, OnDestroy {
// The <div> where we will place the map
@ViewChild("mapViewNode", { static: true }) private mapViewEl: ElementRef;
view: any;
constructor() {}
async initializeMap() {
try {
// Load the modules for the ArcGIS API for JavaScript
const [Map, MapView, webMercatorUtils, Polygon] = await loadModules(["esri/Map", "esri/views/MapView", "esri/geometry/support/webMercatorUtils", "esri/geometry/Polygon"]);
// now do your thing with the modules
// or save the modules on a property for later
// btw, this json is from the link of the question
// I am gonna use it for the initial extent
const poly = Polygon.fromJSON({
"rings":[
[
[ -118.38516, 34.01270 ],
[ -118.38827, 34.01489 ],
[ -118.38813, 34.01602 ],
[ -118.38797, 34.01648 ],
[ -118.38760, 34.01712 ],
[ -118.38733, 34.01696 ],
[ -118.38696, 34.01749 ],
[ -118.38662, 34.01789 ],
[ -118.38689, 34.01805 ],
[ -118.38683, 34.01812 ],
[ -118.38295, 34.01592 ],
[ -118.38516, 34.01270 ]
],
[
[ -118.38661, 34.01486 ],
[ -118.38634, 34.01498 ],
[ -118.38652, 34.01563 ],
[ -118.38670, 34.01559 ],
[ -118.38679, 34.01595 ],
[ -118.38699, 34.01591 ],
[ -118.38707, 34.01507 ],
[ -118.38661, 34.01486 ]
]
],
"spatialReference": {
"wkid": 4326
}
});
const extent = webMercatorUtils.geographicToWebMercator(
// you need to clone the polygon extent because is readonly
// besides why would you change it
poly.extent.clone().expand(3)
);
// Configure the Map
const mapProperties = {
basemap: "streets-vector"
};
const map = new Map(mapProperties);
// Initialize the MapView
const mapViewProperties = {
container: this.mapViewEl.nativeElement,
extent, // use extent
map
};
this.view = new MapView(mapViewProperties);
await this.view.when(); // wait for map to load
return this.view;
} catch (error) {
console.error("EsriLoader: ", error);
}
}
ngOnInit() {
this.initializeMap();
}
ngOnDestroy() {
if (this.view) {
// destroy the map view
this.view.container = null;
}
}
}
Обновить
Здесь у вас есть предыдущий пример с некоторыми изменениями, которые помогут вам понять или обработать ваш случай. Вы увидите, что я сохраняю загруженные модули в свойстве компонента. Тогда я просто использую его позже.
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from "@angular/core";
import { loadModules } from "esri-loader";
@Component({
selector: 'app-esri-map',
templateUrl: './esri-map.component.html',
styleUrls: ['./esri-map.component.scss']
})
export class EsriMapComponent implements OnInit, OnDestroy {
@ViewChild("mapViewNode", { static: true }) private mapViewEl: ElementRef;
view: any;
// to keep loaded esri modules
esriModules = {
geometry: {
Polygon: null,
SpatialReference: null,
support: { webMercatorUtils: null }
},
tasks: {
GeometryService: null,
support: { ProjectParameters: null }
}
};
constructor() {}
async initializeMap() {
try {
// Load the modules for the ArcGIS API for JavaScript
const [
Map,
MapView,
Polygon,
SpatialReference,
webMercatorUtils,
GeometryService,
ProjectParameters
] = await loadModules([
"esri/Map",
"esri/views/MapView",
"esri/geometry/Polygon",
"esri/geometry/SpatialReference",
"esri/geometry/support/webMercatorUtils",
"esri/tasks/GeometryService",
"esri/tasks/support/ProjectParameters"
]);
// save the modules on a property for later
this.esriModules.geometry.Polygon = Polygon;
this.esriModules.geometry.SpatialReference = SpatialReference;
this.esriModules.geometry.support.webMercatorUtils = webMercatorUtils;
this.esriModules.tasks.GeometryService = GeometryService;
this.esriModules.tasks.support.ProjectParameters = ProjectParameters;
// Configure the Map
const mapProperties = {
basemap: "streets"
};
const map = new Map(mapProperties);
// Initialize the MapView
const mapViewProperties = {
container: this.mapViewEl.nativeElement,
map
};
this.view = new MapView(mapViewProperties);
await this.view.when(); // wait for map to load
return this.view;
} catch (error) {
console.error("EsriLoader: ", error);
}
}
// be carefull does not handle point geometries
// point geometry extent is null
zoomToGeometry(geom) {
console.log(`Original Geometry: ${JSON.stringify(geom.toJSON())}`);
const geomSer = new this.esriModules.tasks.GeometryService(
"http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/Geometry/GeometryServer"
);
const outSpatialReference = new this.esriModules.geometry.SpatialReference({ wkid: 102100 });
const params = new this.esriModules.tasks.support.ProjectParameters({
geometries: [geom],
outSpatialReference
});
const self = this;
geomSer.project(params).then(function(result) {
const projectedGeom = result[0];
if (!projectedGeom) {
return;
}
console.log(`Projected Geometry: ${JSON.stringify(projectedGeom.toJSON())}`);
self.view.extent = projectedGeom.extent.clone().expand(3);
});
}
ngOnInit() {
this.initializeMap().then(_ => {
// The map has been initialized
console.log("mapView ready: ", this.view.ready);
const geom = new this.esriModules.geometry.Polygon({
spatialReference: {
wkid: 102704
},
rings: [
[
[
2744913.4668447226,
541568.06113781035
],
[
2744917.4038447142,
541499.65215389431
],
[
2744864.2454864681,
541496.82210706174
],
[
2744813.6648789644,
541494.12952713668
],
[
2744810.2104895562,
541563.64283956587
],
[
2744860.4905727208,
541565.79441006482
],
[
2744913.4668447226,
541568.06113781035
]
]
]
});
this.zoomToGeometry(geom);
});
}
ngOnDestroy() {
if (this.view) {
// destroy the map view
this.view.container = null;
}
}
}
В коде я сохраняю загруженные модули в свойстве esriModules
. Чтобы отслеживать имена модулей, я решил использовать для структурирования значений объектов. Например, Polygon
класс модуля геометрии path esri/geometry/Polygon
— это доступ через this.esriModules.geometry.Polygon
.
Комментарии:
1. Большое вам спасибо за ответ. Не могли бы вы привести пример перепроектирования пользовательских координат с помощью ‘GeometryService’ и ‘pojection’.
2. Рад, что это вам помогает !! .. Я не могу сделать это прямо сейчас, но я обновлю пример, как только смогу
3. Я попытался получить значения проецируемого полигона. Но возвращает неправильные значения. Не могли бы вы, пожалуйста, проверить это. Я обновил код в этом вопросе.
4. Взгляните на обновления и дайте мне знать, если это поможет вам
5. Я проверил код и попытался реализовать в своей системе. Но в функции zoomToGeometry() я не могу получить доступ к this.tasks. GeometryService, this.geometry.SpatialReference, this.tasks.support.Параметры проекта и т.д. Не могли бы вы описать, как использовать функции esri в пользовательской функции. Иногда я получаю сообщение об ошибке «Невозможно назначить «Полигону», поскольку это свойство доступно только для чтения.ts (2540)»