How to setVisibility to a particular layer when clicked?- Openlayers - javascript

I have more than 10 layers , where i have to set one layer to visibility when clicked , I tried a code and its not working. I dont know how to make it better.
var mapClick = [layer1,layer2,layer3......]
if (mapClick == 'layer1'){
layer.setVisibility(true)
}
else {
layer.setVisibility(false)
}

You can modify layer visibility with layer.setVisible(true/false), not setVisibility.
Here the API reference: https://openlayers.org/en/latest/apidoc/module-ol_layer_Layer-Layer.html#setVisible

Related

How to extend Leaflet Icon Class to add data-open attribute to marker HTML?

I'm trying to trigger some functionality based on the click of a marker on a GeoJSON layer in Leaflet. The eventual functionality I'm trying to implement is a flyout, or scroll out type modal populated from the individual feature's JSON attributes. Essentially, I'm trying to implement the functionality in this Tutsplus Tutorial with dynamic feature content based on the marker click.
I THINK I've figured out most of the pieces I need, but I'm struggling with how to add a data attribute, specifically data-open, to the individual marker. Building on an earlier question of mine I've realized it's not enough to just update a DOM element's CSS, but rather my app should be implementing changes based on data attributes to fully get the functionality I want.
From this question I know that this should be done by extending the L.Icon class that Leaflet provides, but the answer is a bit too terse for my current JS skills. I apologize for this effectively being a "ELI5" of a previously asked question, but I'm not sure where the options and slug come into function. I think they're implied by the question, rather than the answer I'm citing and being set on the marker itself.
Here's a simplified version of the the click handler on my markers, which grabs and zooms to location, gets feature info, and populates that info to a div. The zoom functionality works, as does extracting and placing the feature info, but I'm struggling with how to connect the functionality to trigger the modal and place the div with the feature info over the map.
function zoomToFeature(e) {
var latLngs = [e.target.getLatLng()];
var markerBounds = L.latLngBounds(latLngs);
var street = e.target.feature.properties.str_addr;
document.getElementById('street').textContent = street;
mymap.fitBounds(markerBounds);
//where the modal trigger should be
document.getElementById('infoBox').classList.add('is-visible');
}
Here are the event listeners taken from the linked tutorial, which are currently not firing, but I have them working in a standalone implementation:
const openEls = document.querySelectorAll("[data-open]");
const closeEls = document.querySelectorAll("[data-close]");
const isVisible = "is-visible";
//this is the event I want to trigger on marker click
for (const el of openEls) {
el.addEventListener("click", function() {
const modalId = this.dataset.open;
console.log(this);
document.getElementById(modalId).classList.add(isVisible);
});
}
for (const el of closeEls) {
el.addEventListener("click", function() {
this.parentElement.parentElement.parentElement.classList.remove(isVisible);
});
}
document.addEventListener("click", e => {
if (e.target == document.querySelector(".modal.is-visible")) {
document.querySelector(".modal.is-visible").classList.remove(isVisible);
}
});
So, where I'm trying to get is that when my markers are clicked, the trigger the modal to appear over the map. So, I think I'm missing connecting the marker click event with the event that triggers the modal. I think what's missing is adding the data attribute to the markers, or some way chain the events without the data attributes. As there's no direct way to add an attribute to the markers, I try to add slug option on my circle markers:
var circleMarkerOptions = {
radius: 2,
weight: 1,
opacity: 1,
fillOpacity: 0.8,
slug: 'open',
}
and If I read the previously asked question's answer correctly, than extending the Icon Class this way should add a data-open attribute.
L.Icon.DataMarkup = L.Icon.extend({
_setIconStyles: function(img, name) {
L.Icon.prototype._setIconStyles.call(this, img, name);
if (options.slug) {
img.dataset.slug = options.slug;
}
}
});
A stripped down version of my code is here (thanks #ghybs). My full implementation pulls the markers from a PostGIS table. It's a bit hard to see in the Plunker, but this code adds my class to my modal, but doesn't trigger the functionality. It does trigger the visibility if the class is manually updated to modal.is-visible, but the current implementation which renders modal is-visbile doesn't, which I think is because the CSS is interpreted on page load(?) and not in response to the update via the dev tools, while the concatenated css class matches extactly(?). When I do trigger the modal via the dev tools, the close modal listeners don't seem to work, so I'm also missing that piece of the puzzle.
So, it's a work-around to setting the data attribute, but I realized I was shoe-horning a solution where it wasn't needed. Assuming someone ends up with the same mental block. Appropriate listeners on the modal close button and another function passed to the existing marker click listener produce the desired functionality.
const closeM = document.querySelector(".close-modal");
closeM.addEventListener("click", closeMe);
var modal = document.getElementById('infoBox');
and
function modalAction(){
modal.style.display = 'block';
}
function closeMe(){
modal.style.display = 'none';
}

How to hide the marker and zoom on a specified map location by clicking on the marker?

I have a project to finish, and I have 1 month to finish it, I am very late…
I have tried to do what I want to have, but it never worked, I am a beginner in Javascript…
Here is what I would like to have in order to continue my project. Sorry in advance for my English…
I would like that, when I click on a country, markers appears (It works), but I would also like that when I click on a marker, this one disappear and zoom on a specified location (the river, to be precise).
And I also wanted that marker’s popup are shown on mouseover but I didn’t succeed.
I don’t know all the possibilities of javascript. But is it possible to see these things if I zoom out ? (for example : I see the river, I zoom out to the country level and markers appears)
A help would considerably help me in my project and hopefully allow me to finish in time.
Thank you for your attention,
Here is the link of my full code that works till before my last changes :
https://jsfiddle.net/Gio687351/cj9bvrg7/1/
Here is one of the codes that I have tested :
function toggleLayerVisibility(map, selectedLayer) {
if (selectedLayerId && selectedLayerId !== selectedLayer._leaflet_id) {
map.eachLayer(layer => {
if (layer._leaflet_id === selectedLayerId) geojson.resetStyle(layer);
});
}
selectedLayer.setStyle({
opacity: 0,
fillOpacity: 0.0
});
selectedLayerId = selectedLayer._leaflet_id; //save identifier of a selected layer
map.on('zoomend', function() {
if (map.getZoom() < 8 && map.getZoom() > 6){
map.removemarker;
}
else {
map.on('zoomend', {
marker.on('mouseover', function(e) {
L.marker([52.7472, -8.5087]).bindPopup('Limerick, Shannon River').addTo(map);
L.marker([53.34565, -6.32105]).bindPopup('Dublin, River Liffey').addTo(map);
L.marker([47.88363, 7.22444]).bindPopup('Soultz-Haut-Rhin, Le Rimbach').addTo(map); }
}); }
});
I found the solution :
enter image description here

AddThis Layers in Full Screen mode

I'm making a slideshow with full screen functionality (FancyBox 3), it's using the RequestFullScreen method on the container div, which means any other element in the body is not accessible in full screen mode. (correct me if i'm wrong)
I would like to include an AddThis Expanding Share button in the slideshow, but because it's created dynamically by the AddThis js, it appends the Smart Layers before the end of the body, not at the end of the slideshow container div therefore it's not included in the full screen slideshow.
I couldn't find any info on Smart Layers DOM placement in the AddThis API.
What I've tried is seems like a bad idea, to manually appendTo the necessary divs to the slideshow container after the divs are created by AddThis, I managed to "cut and paste" the '.at-expanding-share-button' and it's working so far, but I can't "catch" the '#at-expanded-menu-host' (which is the layer created by AddThis for more sharing options, with the dark background), and I'm not even sure if this method will work properly...
Any help would be appreciated.
I figured it out! :) I thought I share my experience/solution, if anyone has similar difficulties.
What won't work and why:
First I've tried to communicate with the AddThis API to tell it to put its layers to a premade container, which looks like impossible and the AddThis team also told me that there is no solution for manual layer DOM placement, it's always appending those to the end of the body (at least for now, maybe they will implement this option into their API).
Then I've tried to manually append those layers to the Fancy-Box container, which was a dead end because when the slideshow closes, it removes its container from the markup, so the AddThis layers disappeared and I couldn't reinit it (maybe others have some solution for that, but I just couldn't figure it out).
By the way, the "More Sharing Options" layer is created when the share + button is clicked.
My solution:
Instead of appending the layers to the dynamic slideshow container, I've created a static div at the end of the body, appended the layers to it when they are created, and set the Fancy-Box parent div to my container (note that Fancy-Box full screen functionality makes its own div into full screen, so I had to use my own full screen function for the container with the layers and the slideshow).
I've used sindresorhus's screenfull for easier/cross-browser full screen functions.
var FullScreenContainer = $('#container');
// Check if AddThis Layers are ready
var checkLayers = setInterval(function() { appendLayers(); }, 1000);
// Append the layers to FullScreenContainer
function appendLayers() {
var layers = $('.at-expanding-share-button, #_atssh');
if(layers.length > 0){
addthis.layers.refresh();
layers.appendTo(FullScreenContainer);
clearInterval(checkLayers);
console.log('layers added');
}
else {
console.log('not found')
}
}
// Check for more layers when the share icon clicked
$(document).on('click', ".at-expanding-share-button-toggle", function() {
var checkMoreLayers = setInterval(function() { catchLayers(); }, 1000);
function catchLayers() {
var morelayers = $('#at-expanded-menu-host');
if(morelayers.length > 0){
morelayers.appendTo(FullScreenContainer);
clearInterval(checkMoreLayers);
console.log('more layers added');
}
else {
console.log('did not found more')
}
}
});
// Don't forget to disable the full screen function in Fancy-Box,
// then call them when necessary (onInit, clickSlide, clickOutside
// and the close button)
function enterFullscreen() {
screenfull.request($('#container')[0]);
}
function exitFullscreen() {
if (screenfull.isFullscreen) {
screenfull.exit();
$.fancybox.getInstance().close();
}
if (!screenfull.isFullscreen) {
$.fancybox.getInstance().close();
}
}
And you are good to go. I hope this helps for anybody else! :)

OpenLayers zoom scroll events are ignored if no layers are visible

I've noticed that if all OpenLayers.Layers have visibility set to false, I can no longer zoom in and out using my mousewheel. I can still use the OpenLayers.Control.Zoom buttons, but no longer the mouse wheel.
Is there anyway to disable this 'feature'?
Edit:
Here is a jsfiddle link. Set the layer to invisible, then scroll, then set it back to visible. It doesn't change. Now set it invisible, use the zoom control button, then set it back visible.
http://jsfiddle.net/a8kK4/56/
Here's some code for how the map is instantiated because SO won't let me post jsfiddle without it:
var map = new OpenLayers.Map({
div: "map",
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
layers: [ new OpenLayers.Layer.OSM() ]
});
The issue is to do with the onWheelEvent of the MouseWheel handler, see the code here on github. The issue arises with the lines
if (!overScrollableDiv && overMapDiv) {
if (allowScroll) {
as with the map hidden, you will never get it so that all of these conditions are met and therefore the call to this.wheelZoom(e) which actually does the zoom in/out never gets called. The behavior you are seeing is, therefore, by design.
One, somewhat crude way to fix this, is to override the whole function and just set the line where allowScroll is initialized to true, ie, you put the the whole function into your code, after the main OpenLayers.js has downloaded, and just change that one line
OpenLayers.Handler.MouseWheel.prototype.onWheelEvent= function(e){
if (!this.map || !this.checkModifiers(e)) {
return;
}
var overScrollableDiv = false;
//CHANGE THIS LINE TO TRUE
var allowScroll = true;
var overMapDiv = false;
//rest of function .......
};
The problem of doing this is that a scroll will now happen if you use the mouse wheel anywhere. There is probably a more elegant way by changing the conditions under which the values of overMapDiv and allowScroll and overScrollableDiv get set. I could not get this to work on jsFiddle (I think due to version conflicts), but locally it worked as expected. I hope this helps.

onclick even after loading a map - ammap

I am using a small script I modified that uses ammaps library. I use the world map and if I click on certain countries it will load the country's map including the states.
Now, I am struggling on finding a solution to that after I opened a country and click on a state I want to use an onclick event then to just open up the appropriate website for that state. My jsfiddle is here http://jsfiddle.net/xzAx7/ and I would appreciate any help.
This is my code how I load new maps after I clicked on the country. These maps include the states.
map.addListener("clickMapObject", function (event) {
if (event.mapObject.id == "FR") {
loadNewMap("http://www.ammap.com/lib/maps/js/franceLow.js", "franceLow");
}
else if (event.mapObject.id == "RU") {
loadNewMap("http://www.ammap.com/lib/maps/js/russiaLow.js", "russiaLow");
}
else if (event.mapObject.id == "US") {
loadNewMap("http://www.ammap.com/lib/maps/js/usaLow.js", "usaLow");
}
});
I would move the handler to a separate function and would add another if, which would also check the id and generate url.
If you can not generate URL's automatically, then you should not use getAreasFromMap option but add each area in new data provider and set url property for the areas.
if (event.mapObject.id == "FR") {
map.clear();
map.dataProvider.mapVar = AmCharts.maps.franceLow;
map.write("mapdiv");
};

Categories

Resources