ArcGIS API for JS 加载GeoJSON数据
2018-02-05 11:07
1271 查看
ArcGIS API for JS 没有预制的GeoJSON图层(leaflet和openlayers都可以直接加载Geojson格式的图层了),需要加载矢量图层的时候,需要自定义的方式加载,从网上搜索 了一些解决方法,总结出一些经验,如果没有复杂图形,如,多点,复杂多边形的情况下,可以自定义读取Geojson数据,逐个创建相应的点、线、面要素,然后创建Graphic,在添加到GraphicsLayer里,如果有复杂多边形这种情况,就不能使用此方法加载了,需要用到一个转换器,将GeoJSON转换成 ESRIJSON,直接粘代码了,这段代码是网上找的,有个bug,修复了一下
调用:
需要注意,这里的样式的json文件,不要省略节点,之前遇到无法显示样式就是因为省略了一些节点,这些节点在第一种方式
的时候是不需要的。
当然,可以使用ArcMap直接导出ArcGIS的JSON格式,这样前端加载ESRI的JSON格式即可,无须动态转换,转换的效率也不是很高。
缺陷:ArcGIS如果只有矢量图层,没有栅格瓦片图层的情况下,默认都是显示wgs84的坐标系,无法显示web墨卡托坐标系(这在leaflet和openlayers都已经实现了)。但是,如果是使用featureLayer的方式加载地图服务里的矢量图层,可以实现web墨卡托的样式地图。
// =================GeoJSON TO ESRIJSON====================================== function geoJsonConverter() { const gCon: any = {}; /*compares a GeoJSON geometry type and ESRI geometry type to see if they can be safely put together in a single ESRI feature. ESRI features must only have one geometry type, point, line, polygon*/ function isCompatible(esriGeomType, gcGeomType) { let compatible = false; if ((esriGeomType === 'esriGeometryPoint' || esriGeomType === 'esriGeometryMultipoint') && (gcGeomType === 'Point' || gcGeomType === 'MultiPoint')) { compatible = true; } else if (esriGeomType === 'esriGeometryPolyline' && (gcGeomType === 'LineString' || gcGeomType === 'MultiLineString')) { compatible = true; } else if (esriGeomType === 'esriGeometryPolygon' && (gcGeomType === 'Polygon' || gcGeomType === 'MultiPolygon')) { compatible = true; } return compatible; } /*Take a GeoJSON geometry type and make an object that has information about what the ESRI geometry should hold. Includes the ESRI geometry type and the name of the member that holds coordinate information*/ function gcGeomTypeToEsriGeomInfo(gcType) { let esriType, geomHolderId; if (gcType === 'Point') { esriType = 'esriGeometryPoint'; } else if (gcType === 'MultiPoint') { esriType = 'esriGeometryMultipoint'; geomHolderId = 'points'; } else if (gcType === 'LineString' || gcType === 'MultiLineString') { esriType = 'esriGeometryPolyline'; geomHolderId = 'paths'; } else if (gcType === 'Polygon' || gcType === 'MultiPolygon') { esriType = 'esriGeometryPolygon'; geomHolderId = 'rings'; } return { type: esriType, geomHolder: geomHolderId }; } // Convert GeoJSON polygon coordinates to ESRI polygon coordinates function gcPolygonCoordinatesToEsriPolygonCoordinates(gcCoords) { let i, len; const esriCoords = []; let ring; for (i = 0, len = gcCoords.length; i < len; i++) { ring = gcCoords[i]; // Exclusive OR. if ((i === 0) !== ringIsClockwise(ring)) { ring = ring.reverse(); } esriCoords.push(ring); } return esriCoords; } /*rings is Clockwise or not */ function ringIsClockwise(ring) { let sum = 0; let i = 1; const len = ring.length; let prev, cur; while (i < len) { prev = cur || ring[0]; cur = ring[i]; sum += ((cur[0] - prev[0]) * (cur[1] + prev[1])); i++; } return sum > 0; } /*Wraps GeoJSON coordinates in an array if necessary so code can iterate through array of points, rings, or lines and add them to an ESRI geometry Input is a GeoJSON geometry object. A GeoJSON GeometryCollection is not a valid input */ function gcCoordinatesToEsriCoordinates(gcGeom) { let i, len, esriCoords; if (gcGeom.type === 'MultiPoint' || gcGeom.type === 'MultiLineString') { esriCoords = gcGeom.coordinates || []; } else if (gcGeom.type === 'Point' || gcGeom.type === 'LineString') { esriCoords = gcGeom.coordinates ? [gcGeom.coordinates] : []; } else if (gcGeom.type === 'Polygon') { esriCoords = []; if (gcGeom.coordinates) { esriCoords = gcPolygonCoordinatesToEsriPolygonCoordinates(gcGeom.coordinates); } } else if (gcGeom.type === 'MultiPolygon') { esriCoords = []; if (gcGeom.coordinates) { for (i = 0, len = gcGeom.coordinates.length; i < len; i++) { const a = gcPolygonCoordinatesToEsriPolygonCoordinates(gcGeom.coordinates[i]); esriCoords.push(a[0]); } } } return esriCoords; } /*Converts GeoJSON geometry to ESRI geometry. The ESRI geometry is only allowed to contain one type of geometry, so if the GeoJSON geometry is a GeometryCollection, then only geometries compatible with the first geometry type in the collection are added to the ESRI geometry Input parameter is a GeoJSON geometry object.*/ function gcGeometryToEsriGeometry(gcGeom) { let esriGeometry, esriGeomInfo, gcGeometriesToConvert, i, g, coords: any; // if geometry collection, get info about first geometry in collection if (gcGeom.type === 'GeometryCollection') { const geomCompare = gcGeom.geometries[0]; gcGeometriesToConvert = []; esriGeomInfo = gcGeomTypeToEsriGeomInfo(geomCompare.type); // loop through collection and only add compatible geometries to the array // of geometries that will be converted for (i = 0; i < gcGeom.geometries.length; i++) { if (isCompatible(esriGeomInfo.type, gcGeom.geometries[i].type)) { gcGeometriesToConvert.push(gcGeom.geometries[i]); } } } else { esriGeomInfo = gcGeomTypeToEsriGeomInfo(gcGeom.type); gcGeometriesToConvert = [gcGeom]; } // if a collection contained multiple points, change the ESRI geometry // type to MultiPoint if (esriGeomInfo.type === 'esriGeometryPoint' && gcGeometriesToConvert.length > 1) { esriGeomInfo = gcGeomTypeToEsriGeomInfo('MultiPoint'); } // make new empty ESRI geometry object esriGeometry = { // type: esriGeomInfo.type, spatialReference: { wkid: 4326 } }; // perform conversion if (esriGeomInfo.type === 'esriGeometryPoint') { if (!gcGeometriesToConvert[0] || !gcGeometriesToConvert[0].coordinates || gcGeometriesToConvert[0].coordinates.length === 0) { esriGeometry.x = null; } else { esriGeometry.x = gcGeometriesToConvert[0].coordinates[0]; esriGeometry.y = gcGeometriesToConvert[0].coordinates[1]; } } else { esriGeometry[esriGeomInfo.geomHolder] = []; for (i = 0; i < gcGeometriesToConvert.length; i++) { if (gcGeometriesToConvert.length > 1) { coords = gcCoordinatesToEsriCoordinates(gcGeometriesToConvert[i]); for (g = 0; g < coords.length; g++) { esriGeometry[esriGeomInfo.geomHolder].push(coords[g]); } } else { coords = gcCoordinatesToEsriCoordinates(gcGeometriesToConvert[i]); for (g = 0; g < coords.length; g++) { esriGeometry[esriGeomInfo.geomHolder].push(coords[g]); } } } } return esriGeometry; } // Converts GeoJSON feature to ESRI REST Feature. // Input parameter is a GeoJSON Feature object function gcFeatureToEsriFeature(gcFeature) { let esriFeat, esriAttribs; if (gcFeature) { esriFeat = {}; if (gcFeature.geometry) { esriFeat.geometry = gcGeometryToEsriGeometry(gcFeature.geometry); } if (gcFeature.properties) { esriAttribs = {}; for (const prop in gcFeature.properties) { if (gcFeature.properties.hasOwnProperty(prop)) { esriAttribs[prop] = gcFeature.properties[prop]; } } esriFeat.attributes = esriAttribs; } } return esriFeat; } /*Converts GeoJSON FeatureCollection, Feature, or Geometry to ESRI Rest Featureset, Feature, or Geometry*/ gCon.toEsri = function (geoJsonObject) { let outObj, i, gcFeats, esriFeat; if (geoJsonObject) { if (geoJsonObject.type === 'FeatureCollection') { outObj = { features: [] }; gcFeats = geoJsonObject.features; for (i = 0; i < gcFeats.length; i++) { esriFeat = gcFeatureToEsriFeature(gcFeats[i]); if (esriFeat) { outObj.features.push(esriFeat); } } } else if (geoJsonObject.type === 'Feature') { outObj = gcFeatureToEsriFeature(geoJsonObject); } else { outObj = gcGeometryToEsriGeometry(geoJsonObject); } } return outObj; }; return gCon; }
调用:
const jsonf = geoJsonConverter();
countyJSON = jsonf.toEsri(opts.countyJSON);
const features = countyJSON.features;
features.forEach(feature => { feature.attributes = attr; const sym={ 'type': 'esriSFS', 'style': 'esriSFSSolid', 'color': [221, 171, 255], 'outline': { 'type': 'esriSLS', 'style': 'esriSLSSolid', 'color': [255, 255, 255], 'width': 1 } }; feature.symbol = sym; countyLayer.add(new Graphic(feature));
需要注意,这里的样式的json文件,不要省略节点,之前遇到无法显示样式就是因为省略了一些节点,这些节点在第一种方式
的时候是不需要的。
当然,可以使用ArcMap直接导出ArcGIS的JSON格式,这样前端加载ESRI的JSON格式即可,无须动态转换,转换的效率也不是很高。
缺陷:ArcGIS如果只有矢量图层,没有栅格瓦片图层的情况下,默认都是显示wgs84的坐标系,无法显示web墨卡托坐标系(这在leaflet和openlayers都已经实现了)。但是,如果是使用featureLayer的方式加载地图服务里的矢量图层,可以实现web墨卡托的样式地图。
相关文章推荐
- ArcGIS API for JavaScript 加载GeoJSON数据
- 使用arcgis for js 4.x api加载地图和服务
- arcgis api for js 加载百度地图
- 离线谷歌卫星地图加载服务中间件调用示例For ArcGIS JS API
- ArcGIS API FOR JS 加载天地图
- arcgis for js API 4.4 MapImageLayer加载动态图层不出现问题
- arcgis api for javascript 调用天地图,并加载数据arcgis server 发布的数据
- KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据
- arcgis api for js 加载google地图
- ArcGIS Api for Js基础
- ArcGIS API for Silverlight 地图加载进度条类之MapProgressBar
- ArcGIS JS 版军事标绘图(燕尾箭头、钳击箭头、集结地)扇形等自定义图形, ArcGIS For JavaScript API Drawing Tool(绘图工具)————(十七)
- ArcGIS API for Silverlight 调用GP服务加载等值线图层
- arcgis-api-for-js-之要素图层(GraphicsLayer)
- arcgis for js api离线部署
- ArcGis For Silverlight API,地图显示Gis,绘制点,线,绘制图等(二)--Silverlight 配置动态的 webService、动态加载ArcGis地图服务
- [ArcGIS for Android] arcgis runtime for android 中加载矢量数据的实现
- ArcGIS客户端API中加载大量数据的几种解决办法
- arcgis api for js共享干货系列之一自写算法实现地图量算工具
- arcgis api for js 地图查询