mapbox marker rotation/bearing - javascript

is there any chance to set the rotation for a marker? For now, I set the map bearing to the angle of one marker, but the others should have their own marker bearing.
At the moment, I'm using the marker definition like so:
var marker_el = document.createElement('div');
marker_el .className = 'marker';
var new_marker = new mapboxgl.Marker(marker_el)
.setPopup(marker_PopUp);
and set it to the map:
new_marker.setLngLat([lon, lat]);
new_marker.addTo(map);
I'm using JS and react and for the map mapbox-gl

so because there are no answers, I self answer my post with a working solution for me:
var angle = "yourAngle";
var rotateString = "rotate(" + angle + "deg)";
var marker_el = document.createElement('div');
marker_el.className = 'marker';
var new_marker = new mapboxgl.Marker(marker_el);
new_marker.addTo(map);
/* important here is to append the rotate property because the transform
property is already being updated */
marker_el.style.transform = marker_el.style.transform + rotateString;

Related

OpenLayers - Circle coordinates are missing

I would like to have an option to export my drawings as geoJSON files. So far I've managed perfectly with all of them except for the circle, which comes admittedly with no geometries at all!
I know, that GeoJSON format can render a pure circle, and we need to model it as the points as per this thread:
How to define a circle using GeoJson?
https://docs.mongodb.com/manual/tutorial/query-a-2dsphere-index/
I am fully aware of it, that's why I started to modify my code in order to make the circle physically visible.
My problem is very similar to this one:
Can't save features of drawn Circle to JSON in Openlayers 3
and similar to the solution below:
http://geoadmin.github.io/ol3/apidoc/sphere.js.html
After amending the code:
var wgs84Sphere = new ol.sphere(6378137);
var circleInteraction = new ol.interaction.Draw({
geometryFunction: function(coordinates, geometry) {
if (!geometry) {
geometry = new ol.geom.Polygon(null);
}
var center = coordinates[0];
var last = coordinates[1];
var dx = center[0] - last[0];
var dy = center[1] - last[1];
var radius = Math.sqrt(dx * dx + dy * dy);
var circle = ol.geom.Polygon.circular(wgs84Sphere, ol.proj.toLonLat(center), radius);
circle.transform('EPSG:4326', 'EPSG:3857');
geometry.setCoordinates(circle.getCoordinates());
return geometry;
},
type: 'Circle',
source: vectorLayer.getSource()
});
circleInteraction.setActive(false);
circleInteraction.on('drawend', onDrawend );
I have received an error:
Uncaught TypeError: ol.sphere is not a constructor
which is caused by the OpenLayers library upgrade and is not been valid anymore since version 5.0.0.
https://github.com/openlayers/openlayers/issues/9046
regarding this situation, I've tried to change the wgs84Sphere variable
var polygon_geometry = new ol.geom.Polygon;
var wgs84Sphere = ol.sphere.getArea(polygon_geometry, projection='EPSG:4326', radius=6378137)
but it didn't work either
Uncaught TypeError: Cannot read properties of undefined (reading SimpleGeometry.js:170
pointing the line
if (coordinates.length === 0) {
Is it possible to generate the .geoJSON geometries for circle then?
My full JSFiddle is here:
https://jsfiddle.net/pet6h30d/
The parameters for ol.geom.Polygon.circular have also changed so you do not need to construct a sphere, see https://openlayers.org/en/latest/examples/draw-and-modify-geodesic.html If you are not need to modify you only need a polygon
geometryFunction: function(coordinates, geometry, projection) {
if (!geometry) {
geometry = new ol.geom.Polygon([]);
}
var center = ol.proj.transform(coordinates[0], projection, 'EPSG:4326');
var last = ol.proj.transform(coordinates[1], projection, 'EPSG:4326');
var radius = ol.sphere.getDistance(center, last);
var circle = ol.geom.Polygon.circular(center, radius);
circle.transform('EPSG:4326', projection);
geometry.setCoordinates(circle.getCoordinates());
return geometry;
},

Undefinded Global Variable JS

i'm making an android app with cordova. And a I have a noob problem.
I have a map in the index.html, when the index initializes the app obtains the position of the mobile and later does a map with a marker where the mobile is.
The code is this:
var longitud;
var latitud;
function getPosition() {
var options = {
enableHighAccuracy: true,
maximumAge: 1
}
var watchID = navigator.geolocation.getCurrentPosition(onSuccess, onError, options);
function onSuccess(position) {
this.latitud = position.coords.latitude;
this.longitud = position.coords.longitude;
navigator.geolocation.clearWatch(watchID);
mapa();
};
function onError(error) {
alert('code: ' + error.code + '\n' + 'message: ' + error.message + '\n');
}
}
function mapa() {
alert(this.latitud + ' ' + this.longitud);
document.getElementById("mapa").innerHTML = "";
map = new OpenLayers.Map("mapa");
var mapnik = new OpenLayers.Layer.OSM();
var fromProjection = new OpenLayers.Projection("EPSG:4326"); // Transform from WGS 1984
var toProjection = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection
var position = new OpenLayers.LonLat(window.longitud, window.latitud).transform(fromProjection, toProjection);
var zoom = 17;
map.addLayer(mapnik);
map.setCenter(position, zoom);
var lonLat = new OpenLayers.LonLat(this.longitud, this.latitud)
.transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
map.getProjectionObject() // to Spherical Mercator Projection
);
var markers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(markers);
//markers.icon(img/ico-taxi);
markers.addMarker(new OpenLayers.Marker(lonLat));
}
This works well in the index.html. But in other page i want to do the same thing, but instead of showing always, only show it if the users click the accordion because the users must know where are they but I dont want to have a big map in this page all time. When user open the accordion the app creates a map using the same functions because the div id is the same. This works well too, but additionally i want to put the coordinates inside two inputs: inputLat and Input Lon. When user click the accordion in the inputs appears undefined but in theory were defined in index.html and when he clicks in the accordion. But the most strange thing is that, when I close the accordion and I open it again, the coordinates appears. How I can have the coordinates in the input the first time i clik accordion? I give you the code of the accordion functions.
function comprobar() {
var x = document.getElementById("mapa");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
getPosition();
geoLocalizacion();
} else {
x.className = x.className.replace(" w3-show", "");
}
}
function geoLocalizacion () {
document.getElementById("inputLat").value = this.latitud;
document.getElementById("inputLon").value = this.longitud;
}
I tried to read other similar posts and doesn't work. If I add var Longitud = this; int the declaration it shows [object Window]
javascript returns undefind for a globally declared variable
Why a variable defined global is undefined?
Thanks to all I'm so sure that is a noob thing.

How to add text on circle and how to combine circle when zoom out different cicle

I have more than 1000 markers at 3 different location in my Map.
I read Lat and Long from a text file and render it in Google maps and create circle over them on the basis of country name. And count the number of markers in those circle.
Now what i am not able to do is?
(1) I have to print the text of count on those circle (How to do without using Cluster ?)
(2) When i zoom out circle overlaps . So whenever circle overlaps it should combine the 2 radius of these two circles and should make one big circle covering the markers of the two smaller (smaller 2 will now disappear resulting on total of marker on the bigger one only).
My full code to do this (http://prntscr.com/6kt30w) is :
$.ajax({
type: 'GET',
url: './App_Start/TextFile/latLongList3.txt',
dataType: 'text',
}).success(function (data)
{
var s2 = data.replace(/^.*$/, " ").replace(/\r\n/g, " ");
var array = s2.split(/[ ]+/g);
var test = [].concat.apply([], array.map(function (array) { return array.split(/\s+/); }))
var col1 = [];
var col2 = [];
var col3 = [];
var j = 0;
for (var i = 0; i <= test.length - 3; i = i + 3)
{
col1[j] = test[i];
col2[j] = test[i + 1];
col3[j] = test[i + 2];
var myLatlng = new google.maps.LatLng(col3[j], col2[j]);
marker = new google.maps.Marker(
{
position: myLatlng,
map: map,
title: 'Hello World! ' + col1[j]
});
markers.push(marker);
if (j > 0) {
LatLong[j] = myLatlng;
}
j++;
}
})
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I don't want to use MarkerClusterer because it is very small. Yes it's true that it will do the 2 tasks i want to accomplish but the problem i feel with it is when i have markers all over the country then MarkerClusterer just hovers over a very little part of the country whereas i want the circle to hover over all country wherever i have marker and it should have text on it. So if there is any alternative to make the size of cluster such that it cover all the markers in the entire country(because my 1 country is full of markers) and has text on it than any way to do this is welcomed too.
Could some one please help me in solving the 2 problems ?
I have to print the text of count on those circle (How to do without
using Cluster ?)
You can use the following to get count of marker from marker.length
var markers = [];
for (var i = 0; i < 100; i++) {
var latLng = new google.maps.LatLng(data.photos[i].latitude,
data.photos[i].longitude);
var marker = new google.maps.Marker({'position': latLng});
markers.push(marker);
}
To add the count to circle, you can look at this JSFiddel.
I still have to look more your second problem
Finally i found the solution of it.I simply used MarkerClusterer and got it done by increasing its size.
And it works perfectly for me.

Google maps API v3: Adding polyline conflicts with multimarker

I am using Multimarker to add markers with labels to a custom google map. The div containing the label calls a function with onclick. But if I add a polyline to the map, the onclick stops working. I can not figure out why...
This is the code for adding a marker:
var fastMarkers = [];
var myLatlng = new google.maps.LatLng(70,-101);
var marker = new com.redfin.FastMarker(/*id*/1, myLatlng, ["<div onclick='test()'><span>mylabel</span></div>"], null);
fastMarkers.push(marker);
new com.redfin.FastMarkerOverlay(map, fastMarkers);
This is the polyline:
var linepathcoords = [
new google.maps.LatLng(71, -103),
new google.maps.LatLng(73, -107),
];
var linepath=new google.maps.Polyline({
path:linepathcoords,
strokeColor:"#ff0000",
strokeOpacity:0.9,
strokeWeight:2
});
//This next line is what's causing the onclick in the marker to stop working. Why?
linepath.setMap(map);
};
And this is the code for Multimarker:
/*
Copyright 2010 Redfin Corporation
Licensed under the Apache License, Version 2.0:
http://www.apache.org/licenses/LICENSE-2.0
*/
com = {redfin: {}};
/* Construct a new FastMarkerOverlay layer for a V2 map
* #constructor
* #param {google.maps.Map} map the map to which we'll add markers
* #param {Array.<com.redfin.FastMarker>} markers the array of markers to display on the map
*/
com.redfin.FastMarkerOverlay = function(map, markers) {
this.setMap(map);
this._markers = markers;
}
com.redfin.FastMarkerOverlay.prototype = new google.maps.OverlayView();
com.redfin.FastMarkerOverlay.prototype.onAdd = function() {
this._div = document.createElement("div");
var panes = this.getPanes();
panes.overlayLayer.appendChild(this._div);
}
/* Copy our data to a new FastMarkerOverlay
* #param {google.maps.Map} map the map to which the copy will add markers
* #return {FastMarkerOverlay} Copy of FastMarkerOverlay
*/
com.redfin.FastMarkerOverlay.prototype.copy = function(map) {
var markers = this._markers;
var i = markers.length;
var markersCopy = new Array(i);
while (i--) {
markersCopy[i] = markers[i].copy();
}
return new com.redfin.FastMarkerOverlay(map, markers);
};
/* Draw the FastMarkerOverlay based on the current projection and zoom level; called by Gmaps */
com.redfin.FastMarkerOverlay.prototype.draw = function() {
// if already removed, never draw
if (!this._div) return;
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// DGF use fastloop http://ajaxian.com/archives/fast-loops-in-js
// JD Create string with all the markers
var i = this._markers.length;
var textArray = [];
while (i--) {
var marker = this._markers[i];
var divPixel = overlayProjection.fromLatLngToDivPixel(marker._latLng);
textArray.push("<div style='position:absolute; left:");
textArray.push(divPixel.x + marker._leftOffset);
textArray.push("px; top:");
textArray.push(divPixel.y + marker._topOffset);
textArray.push("px;")
if (marker._zIndex) {
textArray.push(" z-index:");
textArray.push(marker._zIndex);
textArray.push(";");
}
textArray.push("'");
if (marker._divClassName) {
textArray.push(" class='");
textArray.push(marker._divClassName);
textArray.push("'");
}
textArray.push(" id='");
textArray.push(marker._id);
textArray.push("' >");
var markerHtmlArray = marker._htmlTextArray;
var j = markerHtmlArray.length;
var currentSize = textArray.length;
while (j--) {
textArray[j + currentSize] = markerHtmlArray[j];
}
textArray.push("</div>");
}
//Insert the HTML into the overlay
this._div.innerHTML = textArray.join('');
}
/** Hide all of the markers */
com.redfin.FastMarkerOverlay.prototype.hide = function() {
if (!this._div) return;
this._div.style.display = "none";
}
/** Show all of the markers after hiding them */
com.redfin.FastMarkerOverlay.prototype.unhide = function() {
if (!this._div) return;
this._div.style.display = "block";
}
/** Remove the overlay from the map; never use the overlay again after calling this function */
com.redfin.FastMarkerOverlay.prototype.onRemove = function() {
this._div.parentNode.removeChild(this._div);
this._div = null;
}
/** Create a single marker for use in FastMarkerOverlay
* #constructor
* #param {string} id DOM node ID of the div that will contain the marker
* #param {google.maps.LatLng} latLng geographical location of the marker
* #param {Array.<string>} htmlTextArray an array of strings which we'll join together to form the HTML of your marker
* #param {string=} divClassName the CSS class of the div that will contain the marker. (optional)
* #param {string=} zIndex zIndex of the div that will contain the marker. (optional, 'auto' by default)
* #param {number=} leftOffset the offset in pixels by which we'll horizontally adjust the marker position (optional)
* #param {number=} topOffset the offset in pixels by which we'll vertically adjust the marker position (optional)
*/
com.redfin.FastMarker = function(id, latLng, htmlTextArray, divClassName, zIndex, leftOffset, topOffset) {
this._id = id;
this._latLng = latLng;
this._htmlTextArray = htmlTextArray;
this._divClassName = divClassName;
this._zIndex = zIndex;
this._leftOffset = leftOffset || 0;
this._topOffset = topOffset || 0;
}
/** Copy the FastMarker
* #return {com.redfin.FastMarker} duplicate of this marker
*/
com.redfin.FastMarker.prototype.copy = function() {
var htmlArray = this._htmlTextArray;
var i = htmlArray.length;
var htmlArrayCopy = new Array(i);
while (i--) {
htmlArrayCopy[i] = htmlArray[i];
}
return new com.redfin.FastMarker(this._id, latLng, htmlArrayCopy, this._divClassName, this._zIndex, this._leftOffset, this._topOffset);
}
Additional info: Before adding the polyline I can use the "inspect" tool in Firefox and select the div and span containing the label. But after adding the polyline the div is gone (the label is still visible on the map, but I can not click it, and I can not select it with the inspect-tool. Also, after adding the polyline I see in the Firefox "inspect"-list that a lot of divs suddenly have "overflow:hidden" on them, and I don't think they had it before. Is this a clue? Also it does not help if I remove the polyline. The onclick function of the labels still don't work. Like, I can add polyline, remove it, add labels, and the labels' onclick is not working. Or I can add labels, add ployline, labels' onclick stops working, remove polyline, labels' onclick still not working.)
There are differences between the Multimarker js-script contained in the zip-file offered for download (2013-03-22) (
http://code.google.com/p/multimarker/) and the js-script accessed through http://multimarker.googlecode.com/svn/trunk/fast-marker-overlay/maps-v3/src/FastMarkerOverlay.js.
The script accessed through http:// says:
line 24:
panes.floatPane.appendChild(this._div);
instead of
panes.overlayLayer.appendChild(this._div);
and line 140:
this.latLng
instead of
latLng
I changed these things in the downloaded script and now it works! Thank you so much geocodezip for helping me solve this! If there is any way I can give you cred for this please tell me. I'm new to the site and I'm not sure of how it works...

Programmatically add 3-D shapes to Bing Maps (Virtual Earth)

How can I programmatically add 3-D shapes to Bing Maps (Virtual Earth)?
Here's some code that should help you:
var map = new VEMap('map_div_id');
// Put you points together and into an array, the 10.0 below is meters above the ground
var point1 = new VELatLong(45.01188,-111.06687, 10.0);
var point2 = new VELatLong(45.01534,-104.06324, 10.0)
var point3 = new VELatLong(41.01929,-104.06, 10.0);
var point4 = new VELatLong(41.003,-111.05878, 10.0);
var points = [point1, point2, point3, point4, point1];
var shape = new VEShape(VEShapeType.Polygon, points);
map.AddShape(shape);
See the following for more information:
VELatLong Class
VEShape Class
AddShape Method

Categories