如何解决Angular ArcGIS esri-loader中的地理ToWebMercator和投影多边形
如何在Angular 10中使用“ geographicToWebMercator”绘制带有环值的多边形。我指的是文档中提供的示例, https://developers.arcgis.com/documentation/core-concepts/features-and-geometries/#polygons 并尝试通过ArcGIS esri-loader使用Angular中的功能。 这是我要参考的文档。 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],542757.74018889666],[2755858.8612924665,542755.48691256344],[2755856.16346322,542804.39462314546],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],],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,} 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',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,]);
// 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,center: this._center,};
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],});
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,});
this.zoomToGeometry(geom);
}
ngOnDestroy() {
if (this._view) {
// destroy the map view
this._view.container = null;
}
}
}
解决方法
第一件事是为您提供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,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,Polygon,SpatialReference,GeometryService,ProjectParameters
] = await loadModules([
"esri/Map","esri/geometry/Polygon","esri/geometry/SpatialReference","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
访问几何模块的esri/geometry/Polygon
类,路径为this.esriModules.geometry.Polygon
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。