Step-8: Implementing Satellite View with fading effect

Step-8: Implementing satellite view with fading effect

Introduction

This guide shows how to implement satellite view with fading effect on a button click.

Getting Started

This guide involves the following steps:

  1. Fetching data
  2. Add Source
  3. Add a styled layer
  4. Add a toggle button

1. Fetching Data

Data is fetched using a custom Ajax call which is a CORS workaround for browsers which cannot load from protocol file:// via httprequests

vms.ajaxcall()

To use the above method please include viamapstrap.js file located in the starter kit.

2. Add source

Sources objects supply data to be shown on the map. This has been explained in step-2. The following code adds a source to the map with the unique ID coastalmask:

map.addSource("coastalmask", {
    type: "geojson",
    data: vmv2geojson(vmv)
});

3. Add a styled layer

As described in step-2 , a layer defines styling for data from a specified source. To add a layer of type fill, specify "type": fill with the paint properties for styling, in this case oceans and seas as shown in the code block below

map.addLayer({
    id: "coastalmask",
    type: "fill",
    "minzoom": 14,
    source: "coastalmask",
    "layout": {
        'visibility': map.getLayoutProperty("orthophoto", 'visibility'),
    },
    'paint': {
        // this trick works best with darkish ocean colors
        'fill-color': '#002',
        'fill-opacity': {
            'base': 0.0,
            'stops': [
                [
                    14,
                    0.1
                ],
                [
                    17,
                    1.0
                ]
            ]
        }
    }
}, 'water_ocean');

4. Add a toggle button

The code block below adds a buttons on Viamap to toggle between the map view and a satellite view by setting the paint properties of the layers.

vmd.addButton(
    'Flyfoto',
    function(e) {

        btntogglefun(e);

        var isOn = e.target.className == "active";

        map.setLayoutProperty(
            "coastalmask", 'visibility', isOn ? 'visible' : 'none');

        map.setPaintProperty('water_ocean', 'fill-opacity', isOn ?
            magicOceanOpacity : defOceanOpacity);
        map.setPaintProperty('water_ocean', 'fill-color', isOn ?
            map.getPaintProperty('coastalmask', 'fill-color') :
            defOceanColor);

    },
    vmd.layerButtonClasses('orthophoto')).click();

setPaintProperty:

setPaintProperty() method sets the value of a paint property in the specified style layer.

setPaintProperty(layerId, name, value, options = {})

Parameters

NameDescription
layerId(string) The ID of the layer to get the paint property from.
name(string) The name of a paint property to get.
value(any) The value of the paint property to set. Must be of a type appropriate for the property

getPaintProperty:

getPaintProperty() method is used to get the paint properties of the layers, in this case the oceans and seas which returns the value of a paint property in the specified style layer.

getPaintProperty(layerId, name)

Parameters

NameDescription
layerId(string) The ID of the layer to get the paint property from.
name(string) The name of a paint property to get.
var defOceanColor = map.getPaintProperty('water_ocean', 'fill-color'),
    defOceanOpacity = map.getPaintProperty(
        'water_ocean', 'fill-opacity'),
    magicOceanOpacity = {
        'base': 1.0,
        'stops': [
            [
                14,
                1.0
            ],
            [
                17,
                0.0
            ]
        ]
    },
    btntogglefun = vmd.layerToggleFunction('orthophoto');

Final code

Here is the final code that shows how to implement satellite view with fading effect on a button click

A working example can be seen here.

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <title>Viamap vektordemo</title>


        <link rel="stylesheet" type="text/css" href="./css/mapbox-gl.css" />

        <script src="./js/mapbox-gl.js"></script>

        <link rel="stylesheet" type="text/css" href="./css/mapbox.css" />
        <script src="./js/mapbox.js"></script>
        <script src="./js/leaflet-hash.js"></script>
        <script src='./js/vmd.js'></script>
        <script src='./js/viamapstrap.js'></script>
        <script src='./js/polyline.js'></script>

        <link href='./css/index.css' rel='stylesheet' />
        <script>
            function vmv2geojson(vmg) {
                var t = vmg[0],
                    d = vmg[1]
                ftype = undefined
                fcoords = [];

                switch (t) {
                    case 'LINESTRING':
                        ftype = 'LineString';
                        break;
                    case 'POLYGON':
                        ftype = 'Polygon';
                        for (var ridx in d) {

                            var pp = polyline.decode(d[ridx], 5, true),
                                lastitem = pp.slice(-1).pop();

                            if (pp[0][0] != lastitem[0] || pp[0][1] != lastitem[1]) {
                                pp.push(pp.slice(0, 1).pop());
                            }
                            fcoords.push(pp);
                        }
                        break;

                    case 'POINT':
                        ftype = 'Point';

                        break;

                    case 'MULTIPOLYGON':
                        ftype = 'MultiPolygon';
                        for (var pidx in d) {
                            var plst = [];
                            for (var ridx in d[pidx][1]) {
                                var pp = polyline.decode(d[pidx][1][ridx], 5, true),
                                    lastitem = pp.slice(-1).pop();
                                if (pp[0][0] != lastitem[0] || pp[0][1] != lastitem[1]) {
                                    pp.push(pp.slice(0, 1).pop());
                                }

                                plst.push(pp);
                            }
                            fcoords.push(plst);
                        }
                        break;

                    case 'MULTILINESTRING':
                        ftype = 'MultiLineString';
                        break;
                    default:
                        console.log('unknown geometry type: ' + t);
                }
                return {
                    'type': 'Feature',
                    'properties': {},
                    'geometry': {
                        'type': ftype,
                        'coordinates': fcoords
                    }
                };
            };
        </script>

    </head>

    <body style="margin:0; padding:0;">
        <nav id="menu"></nav>
        <div id='map' style="position:absolute; top:0; bottom:0; width:100%;"></div>
        <script>
            mapboxgl.setRTLTextPlugin('https:////vektordemo.viamap.net/starterkit/js/mapbox-gl-rtl-text.js');
            var map = new mapboxgl.Map({
                container: 'map',
                style: 'https://demo.tiles.viamap.net/v1/style.json?token=eyJkcGZ4IjogImRlbW8iLCAicHJpdnMiOiAicmZvMjJwcXZqTmtHSk9ZWCJ9.vZ/Dq2DPckC8LBjNjiDARfDqsTevQDu+AjstUlXAIIMK8e1qT+v54u0CvsJYKc9pPlJPOHL1t+B0C5X8vUc7TA',

                hash: true
            });

            map.on('load', function() {
                map.addControl(new mapboxgl.NavigationControl(), 'top-left');


                map.addControl(new mapboxgl.ScaleControl({
                    position: 'bottom-right'
                }));

                vms.ajaxcall(
                    "https://vektordemo.viamap.net/starterkit/data/dk_coastalmask_vmv.json",
                    function(reply) {
                        var vmv = JSON.parse(reply.responseText);
                        map.addSource("coastalmask", {
                            type: "geojson",
                            data: vmv2geojson(vmv)
                        });

                        map.addLayer({
                            id: "coastalmask",
                            type: "fill",
                            "minzoom": 14,
                            source: "coastalmask",
                            "layout": {
                                'visibility': map.getLayoutProperty("orthophoto", 'visibility'),
                            },
                            'paint': {
                                // this trick works best with darkish ocean colors
                                'fill-color': '#002',
                                'fill-opacity': {
                                    'base': 0.0,
                                    'stops': [
                                        [
                                            14,
                                            0.1
                                        ],
                                        [
                                            17,
                                            1.0
                                        ]
                                    ]
                                }
                            }
                        }, 'water_ocean');

                        console.log(map.getLayoutProperty("orthophoto", 'visibility'));

                        console.log(map.getLayoutProperty("coastalmask", 'visibility'));

                        // move the old ocean layer above orthophoto, to avoid alpha sorting darkening the coastline
                        map.moveLayer("water_ocean", 'coastalmask');
                        console.log(map.getLayoutProperty("coastalmask", 'visibility'));

                        //use closure to store some initial variables
                        (function() {
                            // crtitical in order to use the vmd convienience methods
                            vmd.attach(map);

                            var defOceanColor = map.getPaintProperty('water_ocean', 'fill-color'),
                                defOceanOpacity = map.getPaintProperty(
                                    'water_ocean', 'fill-opacity'),
                                magicOceanOpacity = {
                                    'base': 1.0,
                                    'stops': [
                                        [
                                            14,
                                            1.0
                                        ],
                                        [
                                            17,
                                            0.0
                                        ]
                                    ]
                                },
                                btntogglefun = vmd.layerToggleFunction('orthophoto');

                            vmd.addButton(
                                'Flyfoto',
                                function(e) {

                                    btntogglefun(e);

                                    var isOn = e.target.className == "active";

                                    map.setLayoutProperty(
                                        "coastalmask", 'visibility', isOn ? 'visible' : 'none');

                                    map.setPaintProperty('water_ocean', 'fill-opacity', isOn ?
                                        magicOceanOpacity : defOceanOpacity);
                                    map.setPaintProperty('water_ocean', 'fill-color', isOn ?
                                        map.getPaintProperty('coastalmask', 'fill-color') :
                                        defOceanColor);

                                },
                                vmd.layerButtonClasses('orthophoto')).click();
                        })();


                    },
                    function(e) {
                        console.log("error!" + e)
                    }
                );
            });
        </script>
    </body>

</html>

Do you want to try Viamap? Download “starter kit