I'm working on a Map app and I'm having trouble getting marker animated at a time. I'd like to have it so that when a new marker is clicked, the other's animation is removed. I'm a js noob and have been wracking my head. As of now, I have the markers in an array so that I can remove the animation ..but how can I remove the animation of every other marker when setting the animation for another one?..below is the code I've been playing with
for (i in markersArray) {
if (markersArray[i].getAnimation() != null) {
markersArray[i].setAnimation(null);
}
if (marker[i].getAnimation() != null) {
marker[i].setAnimation(null);
} else {
marker[i].setAnimation(google.maps.Animation.BOUNCE);
}
}
The code that you posted seems fine and if it works for you, great. However, if you only want one marker animated at a time, then it might be more efficient, and easier, to just keep a variable of the last animated marker. For example, in your click event or when you add a marker, you could do something like this:
previous_animation.setAnimation(null);
new_marker.setAnimation(google.maps.Animation.BOUNCE);
previous_animation = new_marker;
I ended up coming up with the following code after assigning a unique id to each marker...worked like a charm
for( var i in marker ){
marker[i].setAnimation(null);
if( marker[i].id == item.id ) marker[i].setAnimation(google.maps.Animation.BOUNCE);
}
var new_marker = this;
if(prev_marker) {
if (prev_marker.getAnimation() != null) {
prev_marker.setAnimation(null);
new_marker.setAnimation(google.maps.Animation.BOUNCE);
prev_marker = new_marker;
}
} else {
new_marker.setAnimation(google.maps.Animation.BOUNCE);
prev_marker = new_marker;
}
i prefer #Nick Canzoneri style. Modified it a bit
This is what that i got working, I have my markers in a global variable. Which keeps my markers accessible at all time.
google.maps.event.addListener(marker, 'click', function(event) {
$("input#pickup-"+ marker.id +"").prop('checked', true);
for (var i = window.markers.length - 1; i >= 0; i--) {
window.markers[i].setAnimation();
if(window.markers[i].id === this.id) {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
};
})
Related
Im trying to figure out how to know which Sprite got clicked on
var current_dots:Array<Sprite>= [];
for(i in 0...4){
var page = new Sprite();
current_dots.push(page);
page.on('pointerdown', dot_click);
this.addChild(page);
}
function dot_click(){
trace("CLICKED");
}
since each sprite was declared in the for-loop im not sure how to identify which one is getting clicked
I figured a way to do it was like this
function dot_click(e:InteractionEvent){
for( i in 0...current_dots.length){
if(current_dots[i] == e.currentTarget) {
trace("Clicked")
}
}
}
had to pass the interactive parameter
I am currently trying to use Google Maps with a bunch of markers on it (extracted from a JSON data file). I want to be able to group the markers in one of two categories and be able to switch them off or on.
I am up to the point where the map is working, the pointers are showing and the switch buttons are flicking on and off - all that is left now is to add the markers to groups and bind the switch buttons to displaying/hiding the markers on the map.
I know that I can use marker.setVisible(false/true) but I'm not sure how or where to use it.
I am new to using Google Maps API v3 so any direction with this would be much appreciated.
I have setup a fiddle with what I have so far, you can see it here: https://jsfiddle.net/6n25g3n7/4/
You need to make your markers variable been access to your click event.
Code example:
var markers = [];
function addMarkerToMap(map, markerData){
for(var i = 0; i < markerData.length; i++){
// init marker
markers.push(marker); //push to marker's array
}
}
function clickEvent(){
for(var key in markers){
markers[key].setVisible(true/false);
}
}
fiddle: https://jsfiddle.net/6n25g3n7/5/ Sorry about code is a little bit mess.
If you have any question about code, please comment :)
This one has both markers turning on and off. Check the jsfiddle for all the changes. I had to re-structure some of your code.
function createSwitches(markers){
var html = '<div class="switches"><span class="switch-title">Show Me</span></div>';
// ADD YOU SWITCHES HERE!
// Make sure the same order as the google markers
var all_switches = [
{
html: '<span class="whats-on-wrapper"><span data-target="whats-on" class="switch switch-on">Item Group 2</span></span>',
},
{
html: '<span class="stand-wrapper"><span data-target="stand" class="switch switch-on">Item Group 1</span></span>',
}
];
// Add the main bar element
$('.map-container').prepend(html);
// Loop through all your switches and add them
// with the event
for (var i = 0; i < all_switches.length; i++) {
var element = $(all_switches[i]["html"]);
(function(index, element, markers) {
$(element).on('click', function () {
var this_marker = markers[index];
var current = String(this_marker.visible);
var toggle = ( current === "true") ? false : true;
this_marker.setVisible(toggle);
});
})(i, element, markers)
$('.switches').append($(element))
}
// Set the toggle animation
$('.switches .switch').click(function(){
$(this).toggleClass('switch-on');
$(this).toggleClass('switch-off');
});
}
https://jsfiddle.net/6n25g3n7/8/
I'm updating a project from OL2 to OL3, but I'm stuck on how to redraw features after changing the feature style.
In OL2, this worked:
hidePoints: function(id) {
if (! this.getMap().center) {
return;
}
var i,
feature,
len = this.points.features.length;
if (id !== null) {
for( i = 0; i < len; i++ ) {
feature = this.points.features[i];
if (feature.attributes.aces_id == id) {
feature.style = null;
} else {
feature.style = { display: 'none' };
}
}
} else {
for( i = 0; i < len; i++ ) {
feature = this.points.features[i];
feature.style = { display: 'none' };
}
}
this.points.redraw();
},
In OL3, I tried updating the function to hide the points layer, but redraw() no longer exists and since the layer I am working with is an ol.layer.Vector, I can't find any updateParams options like other sources besides vectors have. Dispatch Event and changed also did not work. I was hoping changed would, but nothing happens.
hidePoints: function(id) {
if (! this.getMap().getView().getCenter()) {
return;
}
var i,
feature,
layerSourceFeatures = this.pointsLayer.getSource().getFeatures(),
len = layerSourceFeatures.length;
if (id !== null) {
for( i = 0; i < len; i++ ) {
feature = this.pointsLayer.getSource().getFeatures()[i];
if (feature.get('aces_id') == id) {
feature.style = null;
} else {
feature.style = { display: 'none' };
}
}
} else {
for( i = 0; i < len; i++ ) {
feature = this.pointsLayer.getSource().getFeatures()[i];
feature.style = { display: 'none' };
}
}
//this.pointsLayer.redraw();
//this.pointsLayer.dispatchEvent(goog.events.EventType.CHANGE);
this.pointsLayer.changed();
},
I'm also wondering if changing the style is done this way (fetching each feature to another var) or if that won't just change that feature and leave the original untouched. Plus always fetching getSource().getFeatures() seems abusive on the performance... but I can't seem to find another way.
Regardless, how is redraw performed in OL3 now to render features whose styles have been altered? A layer can be set as visible, but I don't want to hide/show all the features all the time. Sometimes I just want to hide/show a few according to their given id.
Another way to do it is using a style function and a hidden propertie on the feature:
var style = new ol.Style(...);
function Stylefunction (feature, resolution) {
var prop = feature.getProperties();
if (prop.HIDDEN)
return;
return style;
}
var layer = new ol.layer.Vector({
source: new ol.source.Vector(...),
style: Stylefunction
});
if you change the feature "HIDDEN" propertie, it instant refreshes
So while looking at the documentation over and over, I finally found what would fire the change event, much like seto suggested after.
This is the converted function from OL2 to OL3 that works for me. Redraw is no longer needed since setStyle does it all.
hidePoints: function(id) {
if (! this.getMap().getView().getCenter()) {
return;
}
var i,
feature,
layerSourceFeatures = this.pointsLayer.getSource().getFeatures(),
len = layerSourceFeatures.length;
var emptyImgStyle = new ol.style.Style({ image: '' });
// If an aces id was provided
if (id !== undefined) {
for( i = 0; i < len; i++ ) {
feature = layerSourceFeatures[i];
feature.setStyle(emptyImgStyle);
// Resetting feature style back to default function given in defaultPointStyleFunction()
if (feature.get('aces_id') == id) {
feature.setStyle(null);
}
// Hiding marker by removing its associated image
else {
feature.setStyle(emptyImgStyle);
}
}
}
// No id was provided - all points are hidden
else {
for( i = 0; i < len; i++ ) {
feature = layerSourceFeatures[i];
feature.setStyle(emptyImgStyle);
}
}
},
I can't add comments because I don't have enough reputation, but instead of feature.style = null you might want to call feature.setStyle(null), because this internally triggers the changed event and should instantaneously and automatically change the style. Also feature.style = { display: 'none' } will not work in openlayers 3 because the style needs to be an ol.style.Style object (http://openlayers.org/en/v3.14.2/apidoc/ol.Feature.html#setStyle)
If you have the ID of the features, you can use the source.getFeatureById() method instead of cycling through the features.(http://openlayers.org/en/v3.14.2/apidoc/ol.source.Vector.html#getFeatureById)
Regards rendering, I think using the map's map.render() (at openlayers.org/en/v3.14.2/apidoc/ol.Map.html#render) will re-render the map.
If you just to call a function whenever the map is re-rendered, you can listen on the postrender or postcompose events on the map.
If you create a JSFiddle, I can help you further.
Edit: This example might help you - openlayers.org/en/v3.14.2/examples/dynamic-data.html?q=style
I like this approach for layer toggling (applies to other features, as well):
JAVASCRIPT
<script>
var layerBing = new ol.layer.Tile({
source: new ol.source.BingMaps({
imagerySet: 'Aerial',
key: 'YourKeyBingAccess'
}),
name: 'Bing'
});
/*
* YOUR MAP CODE GOES HERE
*/
function toggleLayer(layerObject) {
var newVisibility = !(layerObject.get('visible'));
layerObject.set('visible', newVisibility);
}
</script>
HTML
<button onclick="toggleLayer(layerBing)">Bing Satellite</button>
<div id="map" class="map"></div>
I'm just wondering if there is a way to open Google Map InfoWindow by keyboard. So far, I can only make it open by click.
I found the following: http://www.visionaustralia.org/digital-access-googlemap
but it only handles the controls and navigation.
$(function(){
//use mapselector="div" if you don't know the map id
var mapSelector = "#map_canvas div";
var attemptInterval = 2;
var maxAttempts = 18;
var mA = 0;
var notYet = true;
var titles = {"pan up":1,"pan down":1,"pan right":1,"pan left":1, "zoom in":1,"zoom out":1,"show street map":1,"show satellite imagery":1};
function addKey(){
mA++;
if(mA > maxAttempts){return;}
$(mapSelector).each(function(index){
var title = this.getAttribute("title")
if(title) title=title.toLowerCase().trim();
if(title in titles){
jqel = $(this);
titles[title] = jqel;
jqel.attr("tabindex","0");
jqel.attr("role","button");
jqel.keydown(function(ev){
if(ev.which==13) {
$(this).trigger("click")
}else if(ev.which==40) {
titles["pan down"].trigger("click");
}else if(ev.which==38) {
titles["pan up"].trigger("click");
}else if(ev.which==37) {
titles["pan left"].trigger("click");
}else if(ev.which==39) {
titles["pan right"].trigger("click");
}else if(ev.which==61 || ev.which == 187) {
titles["zoom in"].trigger("click");
}else if(ev.which==173 || ev.which == 189) {
titles["zoom out"].trigger("click");
}else{
return
}
ev.preventDefault();
});
(function(){
var mo = false;
var bo = jqel.css("border");
var ma = jqel.css("margin");
var bc = jqel.css("background-color");
var op = jqel.css("opacity");
jqel.mouseover(function(){mo=true;});
jqel.mouseout(function(){mo=false;});
jqel.focus(function(){
if(mo)return;
$(this).css({"border":"2px solid blue","margin":"-2px","background-color":"transparent","opacity":"1"});
});
jqel.blur(function(){$(this).css({"border":bo,"margin":ma,"background-color":bc,"opacity":op});});
notYet = false;
})();
}
});
if(notYet){setTimeout(addKey,attemptInterval*1000);}
}
addKey();
});
It works by getting the title of the controls so I tried to add a title to the marker and adding it to the titles array but it doesn't work.
I'm quite new with Google Maps API and JavaScript, any suggestions on where to get started? Thanks!
I'm a bit rusty on my Google Maps API knowledge, but if I remember correctly, the API does indeed give a way to attach a listener to your marker. However, it does not work for keypress events, as you have noticed. For completeness, the basic syntax is this:
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
The addListener function accepts three parameters:
The item on which to attach the event (the marker in this case)
The type of event to listen for
The lamba or function to execute when the event occurs (opening an infoWindow)
The important bit here is the second parameter, the event for which to listen. These are not actual DOM events, but Google's own abstracted events (for better cross-browser support) and thus only a select amount is available - there is no keypress event.
JavaScript, on the other hand, does recognize several key events. I'm cowardly assuming you have jQuery available (from your posted example code), so you could exploit jQuery's keypress function to capture, well, a key press and opening an infoWindow with that:
$(document).keypress(function (event) {
switch (event.which) {
case 102:
// lowercase f
infowindow.open(map, marker);
break;
}
});
This should open your defined infoWindow on your defined marker position. Note that this example does only contain code to open one infoWindow for one marker. But it should give you a general idea.
See the following Fiddle I made for a very rough and simple example, using the 'f' key to open your infoWindow (after clicking in the "result" frame).
I have a Google Maps (API 3) running a custom KML (geoxml3) with polygons containing titles and descriptions.
It all works fine, however I need to change the polygon click which reveals the infowindow to work on hover instead. It is easy enough to create a mouseover listener which runs the click function, however I need the click to run another function, so the click function would get overwritten using this method.
How can I find/copy the code that runs for the polygon click function and apply it to onmouseover instead? Is this possible?
Update: I found this section in the geoxmlv3.js file:
google.maps.event.addListener(gObj, 'click', function (e) {
var iW = this.infoWindow;
iW.close();
iW.setOptions(this.infoWindowOptions);
if (e && e.latLng) iW.setPosition(e.latLng);
else if (this.bounds) iW.setPosition(this.bounds.getCenter());
iW.setContent("<div id='geoxml3_infowindow'>" + iW.getContent() + "</div>");
google.maps.event.addListenerOnce(iW, "domready", function () {
var node = document.getElementById('geoxml3_infowindow');
var imgArray = node.getElementsByTagName('img');
for (var i = 0; i < imgArray.length; i++) {
var imgUrlIE = imgArray[i].getAttribute("src");
var imgUrl = cleanURL(doc.baseDir, imgUrlIE);
if (kmzMetaData[imgUrl]) {
imgArray[i].src = kmzMetaData[imgUrl].dataUrl;
} else if (kmzMetaData[imgUrlIE]) {
imgArray[i].src = kmzMetaData[imgUrlIE].dataUrl;
}
}
});
iW.open(this.map, this.bounds ? null : this);
});
I have tried changing the 'click' event to 'mouseover' but that causes no mouseover or click to work
Here's the solution (after much trial and error!)
google.maps.event.addListener(poly,"mouseover",function(e) {
var iW = this.infoWindow;
iW.close();
iW.setOptions(this.infoWindowOptions);
if (e && e.latLng) iW.setPosition(e.latLng);
else if (this.bounds) iW.setPosition(this.bounds.getCenter());
iW.setContent("<div id='geoxml3_infowindow'>"+iW.getContent()+"</div>");
iW.open(this.map, this.bounds ? null : this);
});
Then just change your click function to something else. Remember to also set your mouseout function to close the infowindow too