CruisersWiki:Ol3chartlet-graticule.js

From CruisersWiki

Jump to: navigation, search
//
/*
   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;
};

// 
Personal tools
advertisement
Friends of Cruisers Wiki