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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...