summaryrefslogtreecommitdiff
path: root/misc/openlayers/examples/mobile-wmts-vienna.js
blob: 45ebecb90243c1f7a966cc27a288544d296cc4a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
var map;

(function() {
    // Set document language for css content 
    document.documentElement.lang = (navigator.userLanguage || navigator.language).split("-")[0];

    // A panel for switching between Aerial and Map, and for turning labels
    // on and off.
    var layerPanel = new OpenLayers.Control.Panel({
        displayClass: "layerPanel",
        autoActivate: true
    });
    var aerialButton = new OpenLayers.Control({
        type: OpenLayers.Control.TYPE_TOOL,
        displayClass: "aerialButton",
        eventListeners: {
            activate: function() {
                if (aerial) {map.setBaseLayer(aerial);}
            }
        }
    });
    var mapButton = new OpenLayers.Control({
        type: OpenLayers.Control.TYPE_TOOL,
        displayClass: "mapButton",
        eventListeners: {
            activate: function() {
                if (fmzk) {map.setBaseLayer(fmzk);}
            }
        }
    });
    var labelButton = new OpenLayers.Control({
        type: OpenLayers.Control.TYPE_TOGGLE,
        displayClass: "labelButton",
        eventListeners: {
            activate: function() {
                if (labels) {labels.setVisibility(true);}
            },
            deactivate: function() {
                if (labels) {labels.setVisibility(false);}
            }
        }
    });
    layerPanel.addControls([aerialButton, mapButton, labelButton]);
    
    var zoomPanel = new OpenLayers.Control.ZoomPanel();
    
    // Geolocate control for the Locate button - the locationupdated handler
    // draws a cross at the location and a circle showing the accuracy radius.
    var geolocate = new OpenLayers.Control.Geolocate({
        type: OpenLayers.Control.TYPE_TOGGLE,
        bind: false,
        watch: true,
        geolocationOptions: {
            enableHighAccuracy: false,
            maximumAge: 0,
            timeout: 7000
        },
        eventListeners: {
            activate: function() {
                map.addLayer(vector);
            },
            deactivate: function() {
                map.removeLayer(vector);
                vector.removeAllFeatures();
            },
            locationupdated: function(e) {
                vector.removeAllFeatures();
                vector.addFeatures([
                    new OpenLayers.Feature.Vector(e.point, null, {
                        graphicName: 'cross',
                        strokeColor: '#f00',
                        strokeWidth: 2,
                        fillOpacity: 0,
                        pointRadius: 10
                    }),
                    new OpenLayers.Feature.Vector(
                        OpenLayers.Geometry.Polygon.createRegularPolygon(
                            new OpenLayers.Geometry.Point(e.point.x, e.point.y),
                            e.position.coords.accuracy / 2, 50, 0
                        ), null, {
                            fillOpacity: 0.1,
                            fillColor: '#000',
                            strokeColor: '#f00',
                            strokeOpacity: 0.6
                        }
                    )
                ]);
                map.zoomToExtent(vector.getDataExtent());
            }
        }
    });
    zoomPanel.addControls([geolocate]);

    // Fallback layer when outside Vienna
    var osm = new OpenLayers.Layer.OSM();

    // Map with navigation controls optimized for touch devices
    map = new OpenLayers.Map({
        div: "map",
        theme: null,
        projection: "EPSG:3857",
        units: "m",
        maxResolution: 38.21851413574219,
        numZoomLevels: 8,
        controls: [
            new OpenLayers.Control.Navigation(),
            new OpenLayers.Control.Attribution(),
            zoomPanel,
            layerPanel
        ],
        eventListeners: {
            moveend: function() {
                // update anchor for permalinks
                var ctr = map.getCenter();
                window.location.hash = "x="+ctr.lon+"&y="+ctr.lat+"&z="+map.getZoom();
                // switch to OSM when outside Vienna
                if (!map.getExtent().intersectsBounds(fmzk.tileFullExtent)) {
                    if (map.baseLayer !== osm) {
                        map.addLayer(osm);
                        map.setBaseLayer(osm);
                    }
                } else if (map.baseLayer === osm) {
                    map.removeLayer(osm);
                }
            }
        }
    });
    layerPanel.activateControl(mapButton);
    layerPanel.activateControl(labelButton);

    // Vector layer for the location cross and circle
    var vector = new OpenLayers.Layer.Vector("Vector Layer");

    // Defaults for the WMTS layers
    var defaults = {
        zoomOffset: 12,
        requestEncoding: "REST",
        matrixSet: "google3857",
        attribution: 'Datenquelle: Stadt Wien - <a href="http://data.wien.gv.at">data.wien.gv.at</a>'
    };

    // The WMTS layers we're going to add
    var fmzk, aerial, labels;
    
    // zoom to initial extent or restore position from permalink
    function zoomToInitialExtent() {
        var extent = fmzk.tileFullExtent,
            ctr = extent.getCenterLonLat(),
            zoom = map.getZoomForExtent(extent, true),
            params = OpenLayers.Util.getParameters("?"+window.location.hash.substr(1));
        OpenLayers.Util.applyDefaults(params, {x:ctr.lon, y:ctr.lat, z:zoom});
        map.setCenter(new OpenLayers.LonLat(params.x, params.y), params.z);
    }

    // Request capabilities and create layers
    OpenLayers.ProxyHost = "proxy.cgi?url=";    
    OpenLayers.Request.GET({
        url: "http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml",
        success: function(request) {
            var format = new OpenLayers.Format.WMTSCapabilities();
            var doc = request.responseText,
                caps = format.read(doc);
            fmzk = format.createLayer(caps, OpenLayers.Util.applyDefaults(
                {layer:"fmzk"}, defaults
            ));
            aerial = format.createLayer(caps, OpenLayers.Util.applyDefaults(
                {layer:"lb"}, defaults
            ));
            labels = format.createLayer(caps, OpenLayers.Util.applyDefaults(
                {layer:"beschriftung", isBaseLayer: false, transitionEffect: 'map-resize'},
                defaults
            ));
            map.addLayers([fmzk, aerial, labels]);
            zoomToInitialExtent();
        }
    });
    
    // Instead of building the layers from the capabilities document, we could
    // look at it ourselves and create the layers manually. If you want to try
    // that, uncomment the following code and remove the "Request capabilities
    // and create layers" block above.
    /*
    var extent = new OpenLayers.Bounds(1799448.394855, 6124949.74777, 1848250.442089, 6162571.828177);
    defaults.tileFullExtent = extent;
    fmzk = new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults({
        url: [
            "http://maps.wien.gv.at/wmts/fmzk/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps1.wien.gv.at/wmts/fmzk/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps2.wien.gv.at/wmts/fmzk/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps3.wien.gv.at/wmts/fmzk/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps4.wien.gv.at/wmts/fmzk/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg"
        ],
        layer: "fmzk",
        style: "pastell"
    },
    defaults));
    aerial = new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults({
        url: [
            "http://maps.wien.gv.at/wmts/lb/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps1.wien.gv.at/wmts/lb/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps2.wien.gv.at/wmts/lb/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps3.wien.gv.at/wmts/lb/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg",
            "http://maps4.wien.gv.at/wmts/lb/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.jpeg"
        ],
        layer: "lb",
        style: "farbe"
    },
    defaults));
    labels = new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults({
        url: [
            "http://maps.wien.gv.at/wmts/beschriftung/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png",
            "http://maps1.wien.gv.at/wmts/beschriftung/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png",
            "http://maps2.wien.gv.at/wmts/beschriftung/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png",
            "http://maps3.wien.gv.at/wmts/beschriftung/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png",
            "http://maps4.wien.gv.at/wmts/beschriftung/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png"
        ],
        layer: "beschriftung",
        style: "normal",
        isBaseLayer: false,
        transitionEffect: 'map-resize'
    },
    defaults));
    map.addLayers([fmzk, aerial, labels]);
    zoomToInitialExtent();
    */

})();

// Reliably hide the address bar on Android and iOS devices. From
// http://blog.nateps.com/how-to-hide-the-address-bar-in-a-full-screen
(function() {
    var page = document.getElementById("map"),
        ua = navigator.userAgent,
        iphone = ~ua.indexOf('iPhone') || ~ua.indexOf('iPod'),
        ipad = ~ua.indexOf('iPad'),
        ios = iphone || ipad,
        // Detect if this is running as a fullscreen app from the homescreen
        fullscreen = window.navigator.standalone,
        android = ~ua.indexOf('Android'),
        lastWidth = 0;

    if (android) {
        // Android's browser adds the scroll position to the innerHeight, just to
        // make this really fucking difficult. Thus, once we are scrolled, the
        // page height value needs to be corrected in case the page is loaded
        // when already scrolled down. The pageYOffset is of no use, since it always
        // returns 0 while the address bar is displayed.
        window.onscroll = function() {
            page.style.height = window.innerHeight + 'px';
        };
    }
    var setupScroll = window.onload = function() {
        // Start out by adding the height of the location bar to the width, so that
        // we can scroll past it
        if (ios) {
            // iOS reliably returns the innerWindow size for documentElement.clientHeight
            // but window.innerHeight is sometimes the wrong value after rotating
            // the orientation
            var height = document.documentElement.clientHeight;
            // Only add extra padding to the height on iphone / ipod, since the ipad
            // browser doesn't scroll off the location bar.
            if (iphone && !fullscreen) height += 60;
            page.style.height = height + 'px';
        } else if (android) {
            // The stock Android browser has a location bar height of 56 pixels, but
            // this very likely could be broken in other Android browsers.
            page.style.height = (window.innerHeight + 56) + 'px';
        }
        // Scroll after a timeout, since iOS will scroll to the top of the page
        // after it fires the onload event
        setTimeout(scrollTo, 0, 0, 1);
    };
    (window.onresize = function() {
        var pageWidth = page.offsetWidth;
        // Android doesn't support orientation change, so check for when the width
        // changes to figure out when the orientation changes
        if (lastWidth == pageWidth) return;
        lastWidth = pageWidth;
        setupScroll();
    })();
})();