i have a geojson layer button and when i click i have to zoom to the particular layer - zooming

this is my layer and i have assigned it to a button, but the zoom is not working when I click the layer button. i tried adding the zoom inside the layer but its not working.
rainfall1 = new ol.layer.Vector({
//title: 'CA_DEVELOPMENT_PLAN',
// extent: [-180, -90, -180, 90],
visible:false,
source: new ol.source.Vector({
url:"./data/village.geojson",
zoom: 12,
format: new ol.format.GeoJSON()
}),
style:function(feature) {
labelStyle.getText().setText(feature.getProperties().CA_NAME);
return style1;
},
declutter: true,
});
document.getElementById("lyr").onclick = function() {
layer1.setVisible(!rainfall1.getVisible());
};
var bindLayerButtonToggle = function (lyr, layer) {
document.getElementById(lyr).onclick = function() {
layer.setVisible(!layer.getVisible());
};
}
bindLayerButtonToggle("lyr", rainfall1);

setVisible will not zoom to a layer, it just turns it on or off.
Instead, you would have to update the view extent, and match it with the layer extent
map.getView().fit(rainfall1.getSource().getExtent());

#JGH's answer might work in some cases but if this is the first time the layer is made visible the source will not be loaded, so if there are no features you will need to wait for it to load before zooming.
if (rainfall1.getSource().getFeatures().length > 0) {
map.getView().fit(rainfall1.getSource().getExtent());
} else {
rainfall1.getSource().once('featuresloadend', function() [
map.getView().fit(rainfall1.getSource().getExtent());
});
}

Related

Leaflet markercluster - on click zoom in then spiderfy

I am clustering on markers at the same location only (i.e. maxClusterRadius = 0). When clicking on the cluster I would like it to centre and zoom in at a specific zoom level (not max zoom), and then immediately spiderfy.
Using the following code, the spiderfy does not occur after the zoom, but will if already at the desired zoom level. I suspect that this is because the cluster is considered to be different after zoom. How can I reference the new cluster (e.g. based on Lat/Long)?
cluster.on('clusterclick', function (a) {
if (map.getZoom() < 19) {
map.once('zoomend', function() { a.layer.spiderfy(); });
map.flyTo(a.layer.getLatLng(), 19);
}
else
a.layer.spiderfy();
});
Same problem. I have this workaround :
var mymap = L.map('mapid_<?= $this->id?>',{
maxZoom:13,
scrollWheelZoom:false,
}).setView([43.38388,-1.3049538], 7);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA'}).addTo(mymap);
var markers = L.markerClusterGroup({
disableClusteringAtZoom: 14,
spiderfyOnMaxZoom: false,
zoomToBoundsOnClick:false,
animate:false
});
clickedMarker="";
mymap.on('zoomend', function() {
if (clickedMarker!=="" && mymap.getZoom()>=mymap.options.maxZoom) {
clickedMarker.__parent.spiderfy();
clickedMarker="";
}
});
markers.on('clusterclick', function (a) {
if (a.layer._childCount>0) {
clusterMarkers = a.layer.getAllChildMarkers();
clickedMarker=clusterMarkers[0];
}
if (mymap.getZoom()>=mymap.options.maxZoom) {
a.layer.spiderfy();
} else {
a.layer.zoomToBounds({padding: [20, 20]});
}
});
Strange but spiderfy is not working with animate option set to true…

ol3 geocoder zoom level issue in chrome

I am trying to add ol3 geocoder control in my project. I have set fix zoom level and it is working in Mozilla and it comes properly with appropriate zoom level but in google chrome it is not working. It takes the location on deep zoom in level. I have to zoom out to check surrounding places.
var geocoder = new Geocoder('nominatim', {
provider: 'google',
key:' AIzaSyClQ0GOW55zhw4PvFh73FyGLHdSd4bJfpM',
lang: 'en',
placeholder: 'Search Location...',
limit: 5,
keepOpen: true,
autoComplete: true,
});
map.addControl(geocoder);
//Listen when an address is chosen
geocoder.on('addresschosen', function(evt){
var
feature = evt.feature,
coord = evt.coordinate,
address_html = feature.get('address_html');
content.innerHTML = '<p>'+address_html+'</p>';
if (coord) {
//alert("if--");
map.getView().setZoom(7);
overlay.setPosition(coord);
} else {
map.getView().setZoom(8);
overlay.setPosition(coord);
}
});
When using the latest version of geocoder (3.0.1) it seems you can set the zoom level within the function. I had the same problem when I switched to new version, but I played around and found that it works perfectly like this:
geocoder.on('addresschosen', function (evt) {
window.setTimeout(function () {
view.setZoom(12);
popup.show(evt.coordinate, evt.address.formatted);
}, 1000);
});
Obviously, use whatever zoom value you like.

react-google-maps and google event listeners - how to catch events?

In my app I'm using react-google-maps (v.6.x.x) to handle api for Google Maps. I'm using markers and infobox to show proper information. Infobox with enableEventPropagation set to true, propagates events to map layer through the infobox - what does that mean? When I have infobox - aka infowindow whe I click on it, and underneath is placed marker, this marker is 'clicked' in first place, and than any html element in infobox. If enableEventPropagation is false - nothing is propagated. So my question is - is there any possibility to add google event listener for react component, for example code:
let infobox = (<InfoBox
onDomReady={() => props.infoBoxReady(infobox)}
defaultPosition={new google.maps.LatLng(props.activeMarker.location[1], props.activeMarker.location[0])}
options={{
closeBoxURL: ``, enableEventPropagation: true, pane: 'mapPane',
position: new google.maps.LatLng(props.activeMarker.location[1], props.activeMarker.location[0]),
alignBottom: true,
pixelOffset: new google.maps.Size(-120, 0)
}}>
How I can use this code to use Google Event Listener
google.maps.event.addListener(infobox, 'domready', function ()
Im getting this kind error
Any clue, how can I set listener for it, or maybe there are other options to set listeners for google map - unfortunately I've to use this library and handle clicks on infobox
The only way I was able to prevent clicks through to the map (stop propagation) and still be able to click items in the in InfoBox is by setting "enableEventPropagation: false" and then adding listeners for the items in the InfoBox on the "onDomReady" prop. This makes sure that the listeners are attached after the InfoBox is rendered. Not sure if thats the best solution, but it did work. Hope that helps someone.
<InfoBox
defaultPosition={new LatLng(marker.position.lat, marker.position.lng)}
onDomReady={
() => {
let closeButton = $('a.close');
let someLink = $('a.info-box-profile');
closeButton.on('click', () => {
// do something with the click
});
someLink.on('click', () => {
// do something with the click
});
}
}
options={{
pixelOffset: new Size(-145, 30),
closeBoxURL: '',
enableEventPropagation: false,
boxStyle: {
overflow: "hidden",
width: "320px",
}
}}>
I wrote this wrapper component that places a <Rectangle/> over the entire map to stop clicks being passed through to the map below. Whilst still allowing you to click things inside the <infoBox/>.
This allows enableEventPropagation to be set to true without creating problems. I then use mouseOver and mouseOut to control how the rectangle works. In my case I use clicking on the rectangle to close my <InfoBox/>. You could just as easily hide and show it.
/* global google */
/* eslint-disable jsx-a11y/no-static-element-interactions */
import React from 'react';
import PropTypes from 'prop-types';
import { Rectangle } from 'react-google-maps';
import GoogleInfoBox from 'react-google-maps/lib/components/addons/InfoBox';
const cardWidth = 235;
const boxShadow = 25; // space for outer shadow
const iconHeight = 2; // the actual height is 48px but we use 6px instead to hide the icon but keep it's shadow
class InfoBox extends React.Component {
constructor(props) {
super(props);
this.closable = true;
}
onClose = () => {
if (this.closable) this.props.onClose();
}
onHover = () => {
this.closable = false;
}
onMouseOut = () => {
this.closable = true;
}
render() {
const { children, position, onClose, type } = this.props;
return (
<div className="info-box">
<Rectangle
options={{ fillColor: '#ffffff', fillOpacity: 0.7, zIndex: 100 }}
bounds={{ north: 90, south: -90, east: 180, west: -180 }}
onClick={this.onClose}
/>
<GoogleInfoBox
position={new google.maps.LatLng(position.lat, position.lng)}
onCloseClick={onClose}
options={{
alignBottom: true,
disableAutoPan: false,
pixelOffset: new google.maps.Size(-(cardWidth / 2) - boxShadow, -iconHeight),
maxWidth: width,
isHidden: false,
visible: true,
pane: 'floatPane',
enableEventPropagation: true,
}}
>
<div
onMouseOver={this.onHover}
onFocus={this.onHover}
onMouseOut={this.onMouseOut}
onBlur={this.onMouseOut}
>
{ children }
</div>
</GoogleInfoBox>
</div>
);
}
}
InfoBox.propTypes = {
children: PropTypes.element.isRequired,
position: PropTypes.shape({
lat: PropTypes.number.isRequired,
lng: PropTypes.number.isRequired,
}).isRequired,
onClose: PropTypes.func,
type: PropTypes.string,
};
export default InfoBox;
You can access the listeners via props on the InfoBox component.
Check them out here: Github docs
You're already using one - onDomReady - there's also:
onCloseClick: `closeclick`,
onContentChanged: `content_changed`,
onPositionChanged: `position_changed`,
onZIndexChanged: `zindex_changed`,

show/hide kml on defined zoom levels

I´m trying to hide/show my own kml files (polygons) depending on zoom levels in OpenLayers - when reached certain zoom level one layer should hide and another show. So far I found this solution (How to load layers depending on zoom level?), but it doesn´t seem to be working in my case. I´m relatively new to javascript and I don´t know if I´m using this right, I also made some changes to the example:
map.events.register("zoomend", map, zoomChanged); //inserted in function init()
function zoomChanged()
{
if (map.getZoom() == 18)
{
kml1.setVisibility (true);
kml2.setVisibility (false);
}
else if (map.getZoom() == 19)
{
kml1.setVisibility (false);
kml2.setVisibility (true);
}
}
I also tried another solution to hide kml1, but in this case my layer isn´t drawn. The LayerSwitcher works - the layer is unselectable in defined zoom levels, but nothing is visible when zoomed out (when layer is already selectable):
var kml1 = new OpenLayers.Layer.Vector("prehled",
{minScale: 1000,}, //1:1000
{
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: "kml/zahrada.kml",
format: new OpenLayers.Format.KML({
extractStyles: true,
extractAttributes: true,
})
})
});
map.addLayer(kml1);
Thanks for any response and advice on this.
Try:
var kml1 = new OpenLayers.Layer.Vector("prehled", {
minResolution: map.getResolutionForZoom(18), // or the desired maximum zoom
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: "kml/zahrada.kml",
format: new OpenLayers.Format.KML({
extractStyles: true,
extractAttributes: true
})
})
});
map.addLayer(kml1);
```

Openlayers zoom in on cluster

Is it possible to zoom in on cluster on click? I also don't know how to disable cluster popup. I read this question , but still have no idea how to do it.
Here is the code:
<html>
<script src="../ol/OpenLayers.js"></script>
<script>
var map, select;
var lat = 53.507;
var lon = 28.145;
var zoom = 7;
function init() {
map = new OpenLayers.Map("map",
{ maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
numZoomLevels: 19,
maxResolution: 156543.0399,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.ScaleLine(),
new OpenLayers.Control.Permalink('permalink'),
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.MousePosition()
] });
var osm = new OpenLayers.Layer.OSM("OpenStreetMap");
map.addLayer(osm);
var lonLat = new OpenLayers.LonLat(lon, lat).transform(map.displayProjection, map.projection);
if (!map.getCenter()) map.setCenter (lonLat, zoom);
var MyStyle = new OpenLayers.Style({
// 'cursor' : 'pointer',
fillColor : "#336699",
fillOpacity : 0.9,
fontColor: "#000080",
fontFamily: "sans-serif, Arial",
// fontWeight: "bold",
externalGraphic: "atm.png",
graphicWidth: 32,
graphicHeight: 37,
label: "${count}",
labelAlign: "ct",
fontSize: "15px",
});
var layer = new OpenLayers.Layer.Vector("Atm", {
protocol: new OpenLayers.Protocol.HTTP({
url: "atm.txt",
format: new OpenLayers.Format.Text({extractStyles: true}),
params: {
extractAttributes: false,
}
}),
styleMap: MyStyle, <!-- --------------------- style -->
projection: map.displayProjection,
strategies: [
new OpenLayers.Strategy.BBOX({ratio: 1, resFactor: 1.1}),
new OpenLayers.Strategy.Cluster({distance: 50, threshold: 3})
]
});
map.addLayer(layer);
// Interaction; not needed for initial display.
selectControl = new OpenLayers.Control.SelectFeature(layer);
map.addControl(selectControl);
selectControl.activate();
layer.events.on({
'featureselected': onFeatureSelect,
'featureunselected': onFeatureUnselect
});
}
// Needed only for interaction, not for the display.
function onPopupClose(evt) {
// 'this' is the popup.
var feature = this.feature;
if (feature.layer) { // The feature is not destroyed
selectControl.unselect(feature);
} else { // After "moveend" or "refresh" events on POIs layer all
// features have been destroyed by the Strategy.BBOX
this.destroy();
}
}
function onFeatureSelect(evt) {
feature = evt.feature;
popup = new OpenLayers.Popup.FramedCloud("featurePopup",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(100,100),
"<h2>"+feature.attributes.title + "</h2>" +
feature.attributes.description,
null, true, onPopupClose);
feature.popup = popup;
popup.feature = feature;
map.addPopup(popup, true);
}
function onFeatureUnselect(evt) {
feature = evt.feature;
if (feature.popup) {
popup.feature = null;
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
}
</script>
</head>
<body onload="init()">
<div id="map"></div>
</body>
</html>
Thanks. Your post does not have much context to explain the code sections; please explain your scenario more clearly.
function onFeatureSelect(event) {
if(!event.feature.cluster) // if not cluster
{
// handle your popup code for the individual feature
}
else
{
// fetch the cluster's latlon and set the map center to it and call zoomin function
// which takes you to a one level zoom in and I hope this solves your purpose :)
map.setCenter(event.feature.geometry.getBounds().getCenterLonLat());
map.zoomIn();
}
}
Using the example code in the linked question I would iterate over all features in the cluster to create a BBX, and then zoom into that extent.
var cluster_bounds=new OpenLayers.Bounds();
event.feature.cluster.forEach(function(feature){
clouster_bounds.extend(feature.geometry);
})
map.zoomToExtent(cluster_bounds)
If you really don't know how to disable the popups then remove these functions:
function onFeatureSelect(evt) {
function onFeatureUnselect(evt) {
And replace it with:
function onFeatureSelect(event) {
var cluster_bounds=new OpenLayers.Bounds();
event.feature.cluster.forEach(function(feature){
cluster_bounds.extend(feature.geometry);
});
map.zoomToExtent(cluster_bounds);
}