OpenLayers 3 Style Function for dynamic feature font setting - function

I am using php and mySQL to generate javascript for the vector layers and features. All is functionally working except I need to be able to control the feature text with zoom, which from my searches requires the use of a style function.
My issue is how/where do I create a function to set what is currently fixed as "font: 140/10 + 'px arial' " tied to the map zoom setting ?
My current design uses a php loop using the database to create the features with unique location and properties:
1) create the feature
2) set the style
3) push into the array iconFeatures0
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.transform([-0.163741,51.507847], 'EPSG:4326', 'EPSG:3857')),
p_title: 'Hyde Park Title',
p_line1: 'Hyde Park',
p_line2: 'Park information ...',
lat: 51.507847,
long: -0.163741,
});
iconFeature.setStyle(
new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 1.0],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
opacity: 0.85,
src: 'test_map/marker_0.png',
size: [52,64],
scale:0.5,
})),
text: new ol.style.Text({
text: 'Hyde Park',
offsetY: -37.5,
fill: new ol.style.Fill({
color: '#FF3300'
}),
font: 140/10 + 'px arial'
})
}),
);
iconFeatures0.push(iconFeature);
//On completion of the loop:
var vectorSource0 = new ol.source.Vector({
features: iconFeatures0
});
vectorLayer0 = new ol.layer.Vector({
source: vectorSource0
});
//setting up the map
var myOSMLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
// Create latitude and longitude and convert them to default projection
var myMapcentre = ol.proj.transform([-0.140180,51.501811], 'EPSG:4326', 'EPSG:3857'); //$long,$lat
var myMapView = new ol.View({
center: myMapcentre,
zoom: 14
})
var myMap = new ol.Map({
controls: ol.control.defaults().extend([
new ol.control.FullScreen()
]),
layers: [myOSMLayer, vectorLayer0],
loadTilesWhileInteracting: true,
target: document.getElementById('demoMap1'),
view: myMapView
});
Thanks in advance.

There are several ways to accomplish this, here is one of them.
First, it would be more efficient if you prepare the styles and simply apply them at different scale, so OpenLayers doesn't have to re-create the styles each time the zoom changes.
Then, instead of styling each feature individually, you would style the entire layer (you can still discriminate by feature "category" within the layer).
At last, you would benefit from the the option to consider the resolution when styling the layer:
vectorLayer0.setStyle(function(feature, resolution) {
return [new ol.style.Style({
text: new ol.style.Text({
font: resolution/1000+'px Calibri,sans-serif',
text: "test",
fill: fill
})
})];
});
You would remove the code iconFeature.setStyle( ... from your code and put the above code after having created vectorLayer0

Related

openlayers3 : center and zoom extent to KML limits

Basic script to display a kml file on a tiled background with openlayer; I just switched from version 2 to 4.65, how can I zoom to the limits of the kml geometry ("vector" here) ?
var wmsSource = new ol.source.TileWMS({
url: "https://sedac.ciesin.columbia.edu/geoserver/wms",
params: {"LAYERS": "other:wwf-terrestrial-biomes", "TILED": true},
serverType: "geoserver"
});
var wmsLayer = new ol.layer.Tile({
opacity: 0.15,
visible: true,
source: wmsSource
});
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: "kml_file.kml",
format: new ol.format.KML()
})
});
var map = new ol.Map({
target: "map-canvas",
layers: [wmsLayer, vector],
controls: ol.control.defaults().extend([
new ol.control.ScaleLine({units: "metric"}),
new ol.control.FullScreen()
]),
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], "EPSG:4326", "EPSG:3857"),
zoom: 3
})
});
I'd like to replace the zoom: 3 and have the map centered and extended to the kml limits ?
Note : I used kmllayer.events.register("loadend", kmllayer, function(evt){map.zoomToExtent(kmllayer.getDataExtent())}); with OpenLayers2...
The following should do what you want
var vectorSource = vector.getSource();
vectorSource.once('change', function(e){
if (vectorSource.getState() === 'ready') {
var extent = vectorSource.getExtent();
map.getView().fit(extent);
}
});
Solution mainly adapted from How to get the extent of a GeoJSON vector source? (changed the variable name & removed second argument in map.getView().fit (required in the old time, now optional, not needed most of the time, like here)
OK, I need to declare the kml source as a separate new ol.source.Vectorvariable, here vectorSource, and read .getExtent() from this variable, not from the ol.layer.Vector :
var wmsSource = new ol.source.TileWMS({
url: "https://sedac.ciesin.columbia.edu/geoserver/wms",
params: {"LAYERS": "other:wwf-terrestrial-biomes", "TILED": true},
serverType: "geoserver"
});
var wmsLayer = new ol.layer.Tile({
opacity: 0.15,
visible: true,
source: wmsSource
});
var vectorSource = new ol.source.Vector({
url: "'.$kml_f.'",
format: new ol.format.KML()
});
var vector = new ol.layer.Vector({
source: vectorSource
});
var map = new ol.Map({
target: "map-canvas",
layers: [wmsLayer, vector],
controls: ol.control.defaults().extend([
new ol.control.ScaleLine({units: "metric"}),
new ol.control.FullScreen()
]),
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], "EPSG:4326", "EPSG:3857"),
zoom: 4,
})
});
vector.once("change", function(e){
var extent = vectorSource.getExtent();
map.getView().fit(extent);
});
Thanks for your help !

Openlayers 4.3.1 is not showing my GeoJSON layer

Please i want to display a layer from GeoJSON file with openlayers 4.3.1 but the result (the vectorLayer variable) show a blank page. What am i missing?
The GeoJSON file is here https://gist.githubusercontent.com/abdounasser202/5d830738ad29e6395743530545bd322b/raw/0c34d9a1ced1879432318b6860c1c21e8e88ef04/quartiers_yaounde.geojson
Here is my JS code
var styles = {
'Polygon': new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'grey',
width: 1
}),
fill: new ol.style.Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
}),
};
var styleFunction = function(feature) {
return styles[feature.getGeometry().getType()];
};
var geojsonObject = 'https://gist.githubusercontent.com/abdounasser202/5d830738ad29e6395743530545bd322b/raw/0c34d9a1ced1879432318b6860c1c21e8e88ef04/quartiers_yaounde.geojson';
console.log("geodata >>> ", geojsonObject);
var vectorSource = new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: geojsonObject
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: styleFunction
});
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
// var extent_degree = [11.4095, 3.71349, 11.5747, 3.9692];
var map = new ol.Map({
layers: [vectorLayer],
target: 'map',
view: new ol.View({
// projection: 'EPSG:4326',
center: ol.proj.fromLonLat([11.5021, 3.8480]),
zoom: 6
})
});
// ol.proj.get('EPSG:4326').setExtent(extent_degree)
var units = map.getView().getProjection().getUnits();
console.log("units >>> ", units);
var projections = map.getView().getProjection();
console.log("projections >>> ", projections);
According your code, you are styling Polygons, but no other geometry types. So you will see only Polygons on your map. Other geometry types will be invisible since they are not styled. The GeoJSON file does not contain Polygons, so indeed you won't see anything.
As far as I can see, the GeoJSON file contains only MultiPolygons. To make them visible, add a style for 'MultiPolygon' in the variable styles, or just change the string 'Polygon' in your code to 'MultiPolygon'.

Trying to display a GeoJSON on Openlayers 3

I am trying to display a geojson file on an openlayers map. The openlayers map is already working, however I cannot figure out how to display the features from the geojson file. The example on their website is unfortunately not very helpful, as it is simply the geojson object being written directly into the file and then accessed later. I wish to take the features from a separate geojson file and display them on the map.
This is what I have so far, copied directly from the example:
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geojsonObject)
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: styleFunction
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
What I need to know is how do I "open" the file and get the features from the geojson file (currently located at the url ..\public\geojson\federal_ridings.geojson) in place of the variable geojsonObject which is already there?
To add GeoJSON layer from external file replace:
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geojsonObject)
});
with
var vectorSource = new ol.source.Vector({
url: '..\public\geojson\federal_ridings.geojson',
format: new ol.format.GeoJSON()
});
ol.format.GeoJSON documentation
Make sure federal_ridings.geojson is a valid JSON file
Demo

Trouble to set coordinates in OpenLayers when using Long and Lat from GoogleMaps

Here is the coordinates of Tehran on Google Maps.
https://www.google.com/maps/place/Tehran/#35.6964895,51.0696315,10z/data=!3m1!4b1!4m2!3m1!1s0x3f8e00491ff3dcd9:0xf0b3697c567024bc
35.6961° N, 51.4231° E
I'm trying to find this coordinate in OpenLayers but I had no luck, here is my code:
map = new ol.Map({
target: 'sample-map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [35.6961, 51.4231],
zoom: 4
})
});
I'm also trying to get current coordinates in degrees but I don't know how.
I'm not entirely sure what is the problem, but I can say this: you need to swap your parameters on center to [51.4231, 35.6961].
According to the Openlayers documentation the center is in the format [x-axis, y-axis] or in your case [East, North].
In your specific case your source projection is NOT lat/long so you have to convert. The following code should work for you:
map = new ol.Map({
target: 'sample-map',
layers: [ new ol.layer.Tile({
source: new ol.source.OSM()
})],
view: new ol.View({
center: ol.proj.transform([51.4231, 35.6961], 'EPSG:4326', new ol.source.OSM().getProjection()),
zoom: 10
})
});

Automagically center a Zoomify image

I am a newbie when it comes to programming and I was hoping y'all could help me. I am trying to automatically center a Zoomify image created through VIPS.
Unfortunately I am having a hard finding out how to center an image. If I use the example from openlayers . org
http://openlayers.org/en/v3.3.0/examples/zoomify.js
I end up centering in a weird way.
Is there anything I am doing wrong or a way I can automatically center the image and zoom that is based on varying image sizes?
Here is a snippet of the code I am using and funny center to make it half passable (but not robust: center: [-20000000,20000000])
var imgWidth = 41056;
var imgHeight = 16168;
var imgCenter = [imgWidth / 2, imgHeight / 2];
// Maps always need a projection, but layers are not geo-referenced, and
// are only measured in pixels. So, we create a fake projection that the map
// can use to properly display the layer.
var proj = new ol.proj.Projection({
code: 'pixel',
units: 'pixels',
extent: [0, 0, imgWidth, imgHeight]
});
var source = new ol.source.XYZ({
url: 'Zoomify_Image/1/{z}/{y}/{x}.jpg'
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: source,
wrapX: false,
projection: proj
}),
new ol.layer.Tile({
source: new ol.source.TileDebug({tileGrid: new ol.tilegrid.XYZ({})}),
wrapX: false,
projection: proj
})
],
//renderer: exampleNS.getRendererFromQueryString(),
view: new ol.View({
projection: proj,
center: [-20000000,20000000],
zoom: 0
})
});
Your data structure does not follow the Zoomify specification, which demands URLs in '/TileGroup{g}/{z}-{x}-{y}.jpg' format. Your URL format, 'Zoomify_Image/1/{z}/{y}/{x}.jpg' is quite a bit different from that, and I guess this is why you are using ol.source.XYZ instead of ol.source.Zoomify.
To fix your code, you will have to use ol.source.TileImage instead of ol.source.XYZ, because ol.source.XYZ currently only supports the EPSG:3857 projection. Assuming you have 7 zoom levels and your directory structure otherwise follows the Zoomify standard, but does not use clipped tiles at the boundaries of the image, your source definition could look something like this:
var source = new ol.source.TileImage({
projection: proj,
tileUrlFunction: function(tileCoord, pixelRatio, projection) {
return url + 'Zoomify_Image/1/' + tileCoord[0] + '-' + tileCoord[1] +
'-' + (-tileCoord[2] - 1) + '.jpg';
},
tileGrid: new ol.tilegrid.Zoomify({
resolutions: [1, 2, 4, 8, 16, 32, 64].reverse()
})
});
Your Tile layer definition would look like this:
new ol.layer.Tile({
extent: [0, -imgHeight, imgWidth, 0],
source: source
})
And finally, your View definition would look like this:
new ol.View({
projection: proj,
center: imgCenter,
zoom: 0,
extent: [0, -imgHeight, imgWidth, 0]
})
If you have tiles that are not 256x256 pixels at the image boundaries, then this approach will not work correctly - the clipped tiles will not be displayed. In this case you should change your Zoomify_Image/ directory structure to match the Zoomify standard and use ol.source.Zoomify, which supports clipped tiles.