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

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);
});
}

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.

Azure Maps - fillColor color attributes for different layers merging

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.

openlayers inside qooxdoo JS framework

i´m using the openlayers drawing example inside my mobile JS (qooxdoo) app and all works fine except that the drawing cursor is above the viewport
so I can draw but I don´t see the cursor and I can only see the drawing after I scroll down.
I have used this qooxdoo example as a base. I have also added all the css rules from the openlayers example to my qooxdoo styles.
Seems like a css position issue, but I can´t seem to find it.
Any help would be appreciated.
/**
* Loads JavaScript library which is needed for the map.
*/
_loadMapLibrary: function() {
var self = this;
var req = new qx.bom.request.Script();
var options = {
singleTile: true,
ratio: 1,
isBaseLayer: true,
wrapDateLine: true,
getURL: function() {
var center = self._map.getCenter().transform("EPSG:3857", "EPSG:4326"),
size = self._map.getSize();
return [
this.url, "&center=", center.lat, ",", center.lon, "&zoom=", self._map.getZoom(), "&size=", size.w, "x", size.h].join("");
}
};
req.onload = function() {
var vector = new OpenLayers.Layer.Vector('Vector Layer', {
styleMap: new OpenLayers.StyleMap({
temporary: OpenLayers.Util.applyDefaults({
pointRadius: 16
}, OpenLayers.Feature.Vector.style.temporary)
})
});
// OpenLayers' EditingToolbar internally creates a Navigation control, we
// want a TouchNavigation control here so we create our own editing toolbar
var toolbar = new OpenLayers.Control.Panel({
displayClass: 'olControlEditingToolbar'
});
toolbar.addControls([
// this control is just there to be able to deactivate the drawing
// tools
new OpenLayers.Control({
displayClass: 'olControlNavigation'
}), new OpenLayers.Control.ModifyFeature(vector, {
vertexRenderIntent: 'temporary',
displayClass: 'olControlModifyFeature'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Point, {
displayClass: 'olControlDrawFeaturePoint'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Path, {
displayClass: 'olControlDrawFeaturePath'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Polygon, {
displayClass: 'olControlDrawFeaturePolygon'
})]);
var osm = new OpenLayers.Layer.OSM();
osm.wrapDateLine = false;
map = new OpenLayers.Map({
div: 'googleMap',
projection: 'EPSG:900913',
numZoomLevels: 18,
controls: [
new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
enableKinetic: true
}
}), new OpenLayers.Control.Zoom(), toolbar],
layers: [osm, vector],
center: new OpenLayers.LonLat(0, 0),
zoom: 1,
theme: null
});
// activate the first control to render the "navigation icon"
// as active
toolbar.controls[0].activate();
}
req.open("GET", this._mapUri);
req.send();
},
Please check the z-Index of the cursor's class. The best way is to modify the z-Index through Chrome's debugger console or Firebug.
Is there any live example of your application available?

Google Maps: Given the Lat Long coordinates

I have the the following Lat Long coordinates (in a JS array), how can we draw the Google Map with markers on these coordinates.
Please give a simple example, as the examples in the API documentation do not really give a conclusive answer or are too complex for me.
43.82846160000000000000, -79.53560419999997000000
43.65162010000000000000, -79.73558579999997000000
43.75846240000000000000, -79.22252100000003000000
43.71773540000000000000, -79.74897190000002000000
Thanks in advance.
You may try this
var map,
locations = [
[43.82846160000000000000, -79.53560419999997000000],
[43.65162010000000000000, -79.73558579999997000000],
[43.75846240000000000000, -79.22252100000003000000],
[43.71773540000000000000, -79.74897190000002000000]
];
var myOptions = {
zoom: 6,
center: new google.maps.LatLng(locations[0][0], locations[0][1]),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map($('#map')[0], myOptions);
var infowindow = new google.maps.InfoWindow(), marker, i;
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent('Current location is: '+ locations[i][0]+', '+locations[i][1]);
infowindow.open(map, marker);
}
})(marker, i));
}
DEMO.
I have worked with google maps and if you just need to place a few markers (make sure you are using API v3) v2 is depreciated and will fall off at some point. Next, your lat/long coords. They need to be clipped down to 9 or 10 chars. I have been unlucky when I go with super-long lat/long Coords values.
Google has a nice tool that lets you build a map with. Start here:
https://developers.google.com/maps/documentation/javascript/
Realize you will need a key on your webhosts domain. You can get your key here:
https://developers.google.com/maps/signup
A long list of demos, with 65 v3 API examples.
https://developers.google.com/maps/documentation/javascript/demogallery
In the demos i found this example which looks to be close. Reuse the code you find by viewing the source. You can see the lat/long coord pairs and how it calls it with this link.
http://gmaps-samples-v3.googlecode.com/svn/trunk/smartinfowindow/js/data.js
Here is a campus map example.
http://beta.gr-3.net/map-api/
Finally, here is the simplest example. A one marker map. Look at the source and reuse it. Hopefully it will be enough to get you started.
https://google-developers.appspot.com/maps/documentation/javascript/examples/marker-simple
I hope all this is helpful.
First, you would create google maps object, somewhere within head tag you would listen for ready event and in the handler have:
var mapOptions =
{
zoom: 10,
center: new google.maps.LatLng( <%= #drawings.first.latitude %>, <%= #drawings.first.longitude %> ),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
This assumes you have a div in your html with id map_canvas.
Than you should be ready to add markers to the page, you should have your coordinates stored in an array, so you can iterate through it and those markers.
for( var i=0; i < coords.length; i++ )
{
latlng = coords[i].latitude + ", " + coords[i].longitude;
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: '',
icon: "http://maps.google.com/mapfiles/marker" + String.fromCharCode(coords.length + 65) + ".png"
});
}

working bar charts/tables with sproutcore

I am currently working on a task which want to display bar charts/tables on the website.
The application is using: sproutcore (1.6) as front-end, Java Restful as backend.
However, I can't find some useful library for charts in sproutcore. Are there any ideas for that?
I search on the website, I feel the google chart tools is quite good, also jFreechart as backend is also a good choice.
I am not sure how to integrate that to sproutcore.
Thanks.
I'm using Flot to display charts on my Sproutcore app.
To use it, you need to create a flot directory inside the frameworks folder which will include the jquery.flot.js file (I've also include jquery.flot.pie.js file) and a core.js file with this content:
sc_require('jquery.flot.js');
sc_require('jquery.flot.pie.js');
Flot = SC.Object.create({
plot: $.plot
}) ;
Then, you need to add this new library to your buildfile :
config :yourapp,
:required => ['flot']
To display your charts in your app, you can use this custom view that I made to work with Flot:
GX.FlotView = SC.View.extend({
classNames: ['flot'],
//ex: [{ data: [[1326366000000, 1500], [1326452400000, 600]], label: 'title of the serie' }, ...]
data: [],
/*
ex: {
legend: { show: true },
series: line, points,
xaxis: { mode: "time", timeformat: "%d/%m/%y", }
grid: { backgroundColor: { colors: ["#FFF", "#fefefe"]}},
}
*/
options: [],
render: function(context, firstTime) {
var frame = this.get('frame'),
data = this.get('data'),
options = this.get('options');
// To avoid an error with flot, we check if width and height > 0
if(frame.width > 0 && frame.height > 0 && data && data.length) {
var layer = this.get('layer'),
plot = Flot.plot(layer, data, options);
}
},
viewDidResize: function() {
this.invokeLast(function() {
if (this.get('isVisibleInWindow')) this.set('layerNeedsUpdate', YES);
});
}.observes('data', 'data.[]'),
});
Then, you just have to bind the data and the option properties with your data.

Resources