Azure Maps - fillColor color attributes for different layers merging - azure-maps

When loading multiple layers, the attribute color for fillColor is merging with fillColor for another layer. I.e. if one is red and the other is blue, both layers are being displayed on map as purple.
Below is the code that is leading to the issue:
//Wait until the map resources are ready.
map.events.add('ready', function () {
//Create a data source and add it to the map.
datasource = new atlas.source.DataSource();
map.sources.add(datasource);
//Add a simple data layer for rendering the data.
var polygonLayer = new atlas.layer.PolygonLayer(datasource, null, {
fillColor: 'red',
fillOpacity: 0.2,
});
//Add a simple data layer for rendering the data.
var polygonLayer2 = new atlas.layer.PolygonLayer(datasource, null, {
fillColor: 'blue',
fillOpacity: 0.2,
});
//Add a simple data layer for rendering the data.
var lineLayer = new atlas.layer.LineLayer(datasource, null, {
strokeColor: 'black',
});
map.layers.add([polygonLayer, polygonLayer2, lineLayer]);
//Read a KML file from a URL or pass in a raw KML string.
atlas.io.read(window.location.origin + '/data/TOC_WGS_KML.kml').then(r => {
if (r) {
//Add the feature data to the data source.
datasource.add(r);
}
});
//Read a KML file from a URL or pass in a raw KML string.
atlas.io.read(window.location.origin + '/data/OZLA.kml').then(r => {
if (r) {
//Add the feature data to the data source.
datasource.add(r);
}
});
//Read a KML file from a URL or pass in a raw KML string.
atlas.io.read(window.location.origin + '/data/Test-Parcels.kml').then(r => {
if (r) {
//Add the feature data to the data source.
datasource.add(r);
}
});
});

That is to be expected. You have two polygon layers rendering the exact same data (twice) with semi-transparent colors.
If you want to render data from one of your files differently from another, you can either use a data driven style expression for the fillColor that looks at properties of your shapes to determine which color to use, or you can use two data sources, each with their own polygon layer. That said, if the polygons are semi-transparent and overlap, you will see the colors merge still.

Related

Display HTML clusters with custom properties using react-map-gl (Mapbox)

I am trying to adapt the example Display HTML clusters with custom properties for react-map-gl.
I got basic clusters without custom styling working (adapted from Create and style clusters):
<ReactMapGL ref={mapRef}>
<Source id="poi-modal-geojson" type="geojson" data={pointsToGeoJSONFeatureCollection(points)}
cluster={true}
clusterMaxZoom={14}
clusterRadius={50}
>
<Layer {...{
id: 'clusters',
type: 'circle',
source: 'poi-modal-geojson',
filter: ['has', 'point_count'],
paint: {
'circle-color': [
'step',
['get', 'point_count'],
'#51bbd6',
100,
'#f1f075',
750,
'#f28cb1'
],
'circle-radius': [
'step',
['get', 'point_count'],
20,
100,
30,
750,
40
]
}
}} />
<Layer {...{
id: 'unclustered-point',
type: 'circle',
source: 'poi-modal-geojson',
filter: ['!', ['has', 'point_count']],
paint: {
'circle-color': '#11b4da',
'circle-radius': 4,
'circle-stroke-width': 1,
'circle-stroke-color': '#fff'
}
}} />
</Source>
</ReactMapGL>
Here, pointsToGeoJSONFeatureCollection(points: any[]): GeoJSON.FeatureCollection<GeoJSON.Geometry> is a function returning a GeoJSON (adapted from here).
However, I need more complex styling of markers and I am trying to adapt Display HTML clusters with custom properties without success so far. I mainly tried to adapt updateMarkers() and to call it inside useEffect():
const mapRef: React.Ref<MapRef> = React.createRef();
const markers: any = {};
let markersOnScreen: any = {};
useEffect(() => {
const map = mapRef.current.getMap();
function updateMarkers() {
const newMarkers: any = {};
const features = map.querySourceFeatures('poi-modal-geojson');
// for every cluster on the screen, create an HTML marker for it (if we didn't yet),
// and add it to the map if it's not there already
for (const feature of features) {
const coords = feature.geometry.coordinates;
const props = feature.properties;
if (!props.cluster) continue;
const id = props.cluster_id;
let marker = markers[id];
if (!marker) {
let markerProps = {
key: 'marker' + id,
longitude: coords[0],
latitude: coords[1],
className: 'mapboxgl-marker-start'
}
const el = React.createElement(Marker, markerProps, null),
marker = markers[id] = el;
}
newMarkers[id] = marker;
if (!markersOnScreen[id]) {
// TODO re-add
// marker.addTo(map);
}
}
// for every marker we've added previously, remove those that are no longer visible
for (const id in markersOnScreen) {
if (!newMarkers[id]) delete markersOnScreen[id];
}
markersOnScreen = newMarkers;
}
// after the GeoJSON data is loaded, update markers on the screen on every frame
map.on('render', () => {
if (!map.isSourceLoaded('poi-modal-geojson')) return;
updateMarkers();
});
}, [points]);
Unfortunately, the Marker created using React.createElement() isn't displayed I am not sure what is the right approach to create Marker elements in updateMarkers() or if my approach is completely wrong.
There is a great article on marker clustering which uses the supercluster and use-supercluster libraries and it makes clustering really easy not only for map box but for other map libraries as well, you can find it here.
You just have to convert your points into GeoJSON Feature objects in order to pass them to the useSupercluster hook and for the calculations to work. It will return an array of points and clusters depending on your current viewport, and you can map through it and display the elements accordingly based on the element.properties.cluster flag.
The properties property of the GeoJSON Feature object can be custom so you can pass whatever you need to display the markers later on when you get the final cluster array.

Can't get custom images to display in Azure Maps as Symbols

I really can't find any good documentation or any good samples on how to do this.
Here is my code. This is running in an Asp.net Core View.
var imageMarker = "https://unpkg.com/leaflet#1.7.1/dist/images/marker-icon.png";
for (var i = 0; i < locationData; i++) {
let imageName = 'image' + i;
map.imageSprite.add(imageName, imageMarker).then(function () {
//Create a data source and add it to the map.
datasource = new atlas.source.DataSource();
map.sources.add(datasource);
//Create a point feature and add it to the data source.
datasource.add(new atlas.data.Feature(new atlas.data.Point(i.longitude, i.latitude), {
name: i.name
}));
//Add a layer for rendering point data as symbols.
map.layers.add(new atlas.layer.SymbolLayer(datasource, null, {
iconOptions: {
//Pass in the id of the custom icon that was loaded into the map resources.
image: imageName,
//Optionally scale the size of the icon.
size: 0.5
},
textOptions: {
//Add some text
textField: name,
//Offset the text so that it appears on top of the icon.
offset: [0, -2]
}
}));
});
}
I'm not getting any errors. The Symbols just don't appear on the map.
The sample linked below works in my map.events.add ready function.
Image Sprite sample
Any help is much appreciated! Thanks!
Here is what ended up working for me. I worked with Microsoft Support on this. locationData contains the image, longitude and latitude. The min and max of both longitude and latitude is passed in as well to set the camera boundry. The biggest issue with my original code was setting iconOptions size to 0.5. The plugin did not like that. It's now set to 1.
function addMarkerSymbols(locationData, min_long, min_lat, max_long, max_lat)
{
map.setCamera({
bounds: [min_long, min_lat, max_long, max_lat],
padding: 50
});
$.each(locationData, function (i, item)
{
map.imageSprite.add('default-icon' + i, item.locationImage);
//Create a data source and add it to the map.
var datasource = new atlas.source.DataSource();
map.sources.add(datasource);
//Add a data set to the data source.
datasource.add(new atlas.data.Feature(new atlas.data.Point([item.longitude, item.latitude]), null));
//Create a symbol layer to render the points.
layer = new atlas.layer.SymbolLayer(datasource, null, {
iconOptions: {
//The map control has built in icons for bar, coffee and restaurant that we can use.
image: 'default-icon' + i,
anchor: 'center',
allowOverlap: true,
size: 1
}
});
map.layers.add(layer);
});
}

React blueimp-load-image rescaling of uploaded image

I'm using the package blueimp-load-image package to load an image in my react application. The image should be resized and put into a canvas afterwards.
This is my code that handles the upload. It can only be an image.
const handleImageUpload = e => {
const [file] = e.target.files;
if (file) {
loadImage(
file,
img => {
setImage(img);
changeOffset(img);
},
{
orientation: true,
maxWidth: innerWidth,
maxHeight: innerHeight,
downsamplingRatio: 0.25,
pixelRatio: window.devicePixelRatio,
imageSmoothingEnabled: true,
imageSmoothingQuality: 'high',
canvas: false,
contain: true,
}
);
}
};
The img gets put into a state variable that gets shown in my canvas (I'm using a KonvaImage from react-konva for that). My problem is that if I don't use pixelRatio: window.devicePixelRatio, the image gets shown correctly, but the quality is poor. If I, however, use pixelRatio: window.devicePixelRatio, the picture is zoomed in.
If I log out the img inside the loadImage this is the output. The first one without pixelRatio, the second one with pixelRatio.
This is what the image on the screen looks like (again first one without pixelRation, the second one with pixelRatio):
I hope somebody can help me with my problem. I would of course also be open for a different way of resizing the images if it works better.
Thanks in advance!

drawing a itinerary on maps using a linestring with openlayers 3

Im new on openlayers so i try to make a itinerary using tow point, i can draw a line but not itinerary.
here is my code
var lineFeature = new ol.Feature(
new ol.geom.LineString([ol.proj.transform([4.658166 ,44.199790], 'EPSG:4326', 'EPSG:3857'), ol.proj.transform([ 1.425145 , 43.340356 ],'EPSG:4326', 'EPSG:3857')])
);
var style = {
strokeColor: '#0000ff',
strokeOpacity: 0.5,
strokeWidth: 5
};
var vectorlinenew = new ol.layer.Vector({
source: new ol.source.Vector({
features:[ lineFeature ]
}),
name:'linefeature'
});
map.addLayer(vectorlinenew);
I'm not sure I got your question right, but I believe it draws the line just because you passed just two points to ol.geom.LineString whereas it accepts multiple points and would draw the line over all of them. So all you have to do is just pass an array of all your points to ol.geom.LineString and it will draw the itinerary line.

Google Maps GOverviewMapControl() and GAdsManager

I have a GMap2 object with a GOverviewMapControl and a GAdsManager, but they both appear in the lower right hand corner.
How can I get them to appear in different parts of the map?
Here's my Overview:
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
here's my Ads
var adsManagerOptions = {
maxAdsOnMap: 2,
style: 'adunit',
channel: 'XXXXXXXXX'
};
adsManager = new GAdsManager(map, publisherID, adsManagerOptions);
adsManager.enable();
The position property of the GAdsManagerOptions class will allow you to set the position of the GAdsManager. The options are passed in to the GAdsManager constructor.
Unfortunately, the GOverviewMapControl is not as flexible. According to the documentation, "Unlike other controls, you can only place this control in the bottom right corner of the map (G_ANCHOR_BOTTOM_RIGHT)."
I have no way to test this at the moment, but your options will probably look something like:
var adsManagerOptions = {
maxAdsOnMap: 2,
style: 'adunit',
channel: 'XXXXXXXXX',
position: new GControlPosition(G_ANCHOR_BOTTOM_LEFT)
};

Resources