From CruisersWiki
//
/*
Graticule.js
Copyright (c) 2016 Vadim Shlyakhov
Licensed MIT
*/
// add coordinate grid layer
function graticuleLayer(map) { // after http://map.openseamap.org/javascript/grid_wgs.js
var gridSteps = [
// in seconds
//~ 3 / 3600, // 0.05'
6 / 3600, 12 / 3600, 30 / 3600, // 0.1' 0.2' 0.5'
// in minutes
1 / 60, 2 / 60, 3 / 60, 5 / 60, 10 / 60, 20 / 60, 30 / 60,
// in degrees
1, 2, 3, 4, 6, 10, 15, 30, 45];
var gridPixelStep = 100;
// Find matching grid step
var getGridStep = function (distance) {
for (var i=0; i<gridSteps.length; i++) {
if (distance < gridSteps[i])
return gridSteps[i];
}
return gridSteps[i-1];
};
// Format label
var zeroPad = function (x, int_places, dec, zero_pad) {
var pad = ' ' // spaces there
var sign = ''
var places = dec > 0 ? int_places+dec+1 : int_places
if (zero_pad == null || zero_pad) {
var pad = '00000000000000000000'
if (x < 0) {
x = Math.abs(x)
places--
sign = '-'
}
}
return sign + (pad + x.toFixed(dec)).slice(-places)
};
var formatDegrees = function (deg, format, isLon) {
var adeg = Math.abs(deg);
return ''
+ zeroPad(Math.floor(adeg), isLon ? 3 : 2) + "°"
+ (format == 'd' ? '' : zeroPad((adeg * 60) % 60, 2, format == 'dm' ? 0 : 1) + "'")
+ (isLon ? (deg < 0 ? 'W' : 'E') : (deg < 0 ? 'S' : 'N'));
};
var view = map.getView();
// layer loader
var loader = function(extent, resolution, projection) {
/**
* @param {ol.Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {ol.proj.Projection} projection Projection.
* @this {ol.source.Vector|ol.VectorTile}
*/
var view_proj = view.getProjection();
var geo_proj = 'EPSG:4326';
var map_size = map.getSize();
var lonlat_extent = ol.proj.transformExtent(extent, view_proj, geo_proj);
// clip extent to max values
var x1 = Math.max (-180, lonlat_extent[0]);
var x2 = Math.min ( 180, lonlat_extent[2]);
var y1 = Math.max ( -85, lonlat_extent[1]);
var y2 = Math.min ( 85, lonlat_extent[3]);
// grid step
var step = getGridStep((lonlat_extent[3] - lonlat_extent[1]) / map_size[1] * gridPixelStep);
var labelFormat = step % 1 ? ((step * 60)% 1 ? 'dm.m' : 'dm') : 'd'; // round degrees number
var features = [];
// line style
var strokeStyle = new ol.style.Stroke({
color: [102, 102, 102, 255 * 0.8], // "#666666",
width: 1,
//~ strokeOpacity: 0.8
});
// Vertical lines
for (var x = Math.ceil(x1 / step) * step + (x1 == -180 ? step : 0); x <= x2; x += step) {
var l = new ol.geom.LineString([
ol.proj.transform([x, y1], geo_proj, view_proj),
ol.proj.transform([x, y2], geo_proj, view_proj)
]);
var f = new ol.Feature(l);
f.setStyle(new ol.style.Style({
stroke: strokeStyle,
text: new ol.style.Text({
text: formatDegrees (x, labelFormat, true),
textAlign: 'end',
textBaseline: 'top',
offsetX: 0,
offsetY: - map_size[1] / 2,
rotation: - Math.PI / 2,
scale: 1.5,
// labelAlign: "lt",
}),
}));
features.push (f);
}
// Horizontal lines
for (var y = Math.ceil(y1 / step) * step; y <= y2; y += step) {
var l = new ol.geom.LineString([
ol.proj.transform([x1, y], geo_proj, view_proj),
ol.proj.transform([x2, y], geo_proj, view_proj)
]);
var f = new ol.Feature(l);
f.setStyle(new ol.style.Style({
stroke: strokeStyle,
text: new ol.style.Text({
text: formatDegrees (y, labelFormat, false),
textAlign: 'end',
textBaseline: 'top',
offsetX: map_size[0] / 2,
offsetY: 0,
rotation: 0,
scale: 1.5,
//~ labelAlign: "lt",
}),
}));
features.push (f);
}
this.addFeatures(features);
};
var graticule = new ol.layer.Vector({
title: 'Graticule',
visible: false,
source: new ol.source.Vector({
loader: loader,
strategy: ol.loadingstrategy.bbox
})
});
graticule.set('noclickable', true);
var onChangeCenterZoom = function () {
graticule.getSource().clear();
}
view.on('change:center', onChangeCenterZoom);
view.on('change:resolution', onChangeCenterZoom);
return graticule;
};
//