Hi,
I want to reproject my FeatureLayer with client side Point features (wkid: 31468) into my streets basemap (default wkid: 4326).
How can I do this. See me code below, there is one point in "features". There will be several thousand points in future to be displayed.
var map = new Map({
basemap: "streets"
});
var view = new MapView({
center: [10.757158, 48.181567],
container: "viewDiv",
map: map,
zoom: 15
});
var features = [
{
geometry: new Point({
x: 4408681.069,
y: 5338984.143
})
}
];
var lyr = new FeatureLayer({
fields: [
{
name: "ObjectID",
alias: "ObjectID",
type: "oid"
}
],
objectIdField: "ObjectID",
geometryType: "point",
spatialReference: { wkid: 31468 },
source: features,
renderer: baumRenderer //custom renderer
});
map.add(lyr);
Thank you very much for your help.
Michael
Solved! Go to Solution.
To go a little further, the only projection that is included in the JS API is WGS84 to web mercator and web mercator to WGS84. Everything else is done on the backend.
There is a public geometry service that you can use located at https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer (only supports json, no html)
Michael,
First thing is the esri default base maps are 102100 not 4326. To reproject your data you need to use the GeometryService project method.
To go a little further, the only projection that is included in the JS API is WGS84 to web mercator and web mercator to WGS84. Everything else is done on the backend.
There is a public geometry service that you can use located at https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer (only supports json, no html)
Tank you for your fast answers.
@Thomas Solow, does this mean I have to outsource my javascript code from html/php file to .json and do there the projection? Could I do that also offline?
You'll need an internet connection to use the geometry service. You can do this from JS normally, I just meant that most esri services have an HTML UI but the geometry service I linked doesn't.
Here's a sample showing how to project a list of geometries (only one in the example) and then add each one to a layer as a new graphic: JS Bin - Collaborative JavaScript Debugging
Thank you very much for the example code. That worked for me perfectly.
To come back to the offline issue - Is there another possibility to transform/project features? The success of my application depends amongst others on the possibility to use it offline. Could I do that for example with python in background?
Hi Thomas,
what is happening now - when I execute my code (token from your sample), no objects are displayed in browser. When I refresh website, sometimes all objects are displayed, sometimes just a handful of objects. In your code you are using the then()-function. So what can be the problem? I think it's the GeometryService. It seems to be arbitrary hhow many objects are displayed. Is there no possibility to project whole FeatureLayers? Isn't loading each point into the project()-function very expensive?
You can see my code below.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Test</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<script src="https://js.arcgis.com/4.4/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic",
"esri/geometry/Point",
"esri/symbols/SimpleMarkerSymbol",
"esri/tasks/GeometryService",
"esri/tasks/support/ProjectParameters",
"esri/geometry/SpatialReference",
"esri/widgets/Compass",
"esri/widgets/BasemapToggle",
"esri/widgets/Track",
"esri/renderers/SimpleRenderer",
"esri/geometry/SpatialReference",
"dojo/domReady!"
], function (Map, MapView, FeatureLayer, Graphic, Point, SimpleMarkerSymbol, GeometryService, ProjectParameters, SpatialReference, Compass, BasemapToggle, Track, SimpleRenderer, SpatialReference
) {
var mapCenter = [10.734112, 48.174298];
var map = new Map({
basemap: "streets"
});
var geoSvc = new GeometryService({
url: 'https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer'
});
var view = new MapView({
center: mapCenter,
container: "viewDiv",
map: map,
zoom: 15
});
// renderer
var sr = new SimpleRenderer({
symbol: new SimpleMarkerSymbol({
style: "square",
color: "blue",
size: "8px", // pixels
outline: { // autocasts as esri/symbols/SimpleLineSymbol
color: [ 255, 255, 0 ],
width: 3 // points
}
})
});
// create new layer, starts emtpty
var lyr = new FeatureLayer({
fields: [
{
name: "ObjectID",
alias: "ObjectID",
type: "oid"
}
],
objectIdField: "ObjectID",
geometryType: "point",
spatialReference: { wkid: 102100 },
source: [],
renderer: sr //custom renderer
});
var feature = [
new Point({
x: "4408069.551",
y: "5338730.568",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature, lyr);
var feature1 = [
new Point({
x: "4408681.069",
y: "5338984.143",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature1, lyr);
var feature2 = [
new Point({
x: "4408132.398",
y: "5339858.609",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature2, lyr);
var feature3 = [
new Point({
x: "4407338.453",
y: "5340594.881",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature3, lyr);
var feature4 = [
new Point({
x: "4407532.633",
y: "5340506.362",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature4, lyr);
var feature5 = [
new Point({
x: "4403489.605",
y: "5340682.593",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature5, lyr);
var feature6 = [
new Point({
x: "4402731.486",
y: "5342881.800",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature6, lyr);
var feature7 = [
new Point({
x: "4402384.333",
y: "5339734.656",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature7, lyr);
var feature8 = [
new Point({
x: "4401578.794",
y: "5342314.299",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature8, lyr);
var feature9 = [
new Point({
x: "4402966.449",
y: "5339372.039",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature9, lyr);
var feature10 = [
new Point({
x: "4407610.834",
y: "5338804.822",
spatialReference: { wkid: 31468 }
})
];
projectPoints (geoSvc, feature10, lyr);
// add layer to map
map.add(lyr);
// project each geomtry, then add to layer's source
function projectPoints(geoSvc, geometries, lyr){
geoSvc.project({
geometries: geometries,
outSpatialReference: SpatialReference.WebMercator
}).then(geometries => {
let features = geometries.map((geometry, idx) => {
return new Graphic({
geometry: geometry,
attributes: {
objectID: idx - 1
}
});
});
lyr.source = lyr.source.concat(features);
});
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
Best Regards,
Michael
Looks like the problem is with concat.
Try changing this line:
lyr.source = lyr.source.concat(features);
to this:
features.forEach(f => lyr.source.push(f));
As far as doing the projections locally, I'm sure it's possible, it's just a question of finding the right code. You might want to look at some open source tools for this kind of thing, like proj4. There also may be some way to interface with Esri software with python, which would allow you to set up a local web server and use that to feed projections to the browser.