1 | // Use proxy to get same origin URLs for tiles that don't support CORS. |
---|
2 | OpenLayers.ProxyHost = "proxy.cgi?url="; |
---|
3 | |
---|
4 | var map, cacheWrite, cacheRead1, cacheRead2; |
---|
5 | |
---|
6 | function init() { |
---|
7 | map = new OpenLayers.Map({ |
---|
8 | div: "map", |
---|
9 | projection: "EPSG:900913", |
---|
10 | layers: [ |
---|
11 | new OpenLayers.Layer.OSM("OpenStreetMap (CORS)", null, { |
---|
12 | eventListeners: { |
---|
13 | tileloaded: updateStatus, |
---|
14 | loadend: detect |
---|
15 | } |
---|
16 | }), |
---|
17 | new OpenLayers.Layer.WMS("OSGeo (same origin - proxied)", "http://vmap0.tiles.osgeo.org/wms/vmap0", { |
---|
18 | layers: "basic" |
---|
19 | }, { |
---|
20 | eventListeners: { |
---|
21 | tileloaded: updateStatus |
---|
22 | } |
---|
23 | }) |
---|
24 | ], |
---|
25 | center: [0, 0], |
---|
26 | zoom: 1 |
---|
27 | }); |
---|
28 | // try cache before loading from remote resource |
---|
29 | cacheRead1 = new OpenLayers.Control.CacheRead({ |
---|
30 | eventListeners: { |
---|
31 | activate: function() { |
---|
32 | cacheRead2.deactivate(); |
---|
33 | } |
---|
34 | } |
---|
35 | }); |
---|
36 | // try loading from remote resource and fall back to cache |
---|
37 | cacheRead2 = new OpenLayers.Control.CacheRead({ |
---|
38 | autoActivate: false, |
---|
39 | fetchEvent: "tileerror", |
---|
40 | eventListeners: { |
---|
41 | activate: function() { |
---|
42 | cacheRead1.deactivate(); |
---|
43 | } |
---|
44 | } |
---|
45 | }); |
---|
46 | cacheWrite = new OpenLayers.Control.CacheWrite({ |
---|
47 | imageFormat: "image/jpeg", |
---|
48 | eventListeners: { |
---|
49 | cachefull: function() { |
---|
50 | if (seeding) { |
---|
51 | stopSeeding(); |
---|
52 | } |
---|
53 | status.innerHTML = "Cache full."; |
---|
54 | } |
---|
55 | } |
---|
56 | }); |
---|
57 | var layerSwitcher = new OpenLayers.Control.LayerSwitcher(); |
---|
58 | map.addControls([cacheRead1, cacheRead2, cacheWrite, layerSwitcher]); |
---|
59 | layerSwitcher.maximizeControl(); |
---|
60 | |
---|
61 | |
---|
62 | |
---|
63 | // add UI and behavior |
---|
64 | var status = document.getElementById("status"), |
---|
65 | hits = document.getElementById("hits"), |
---|
66 | cacheHits = 0, |
---|
67 | seeding = false; |
---|
68 | var read = document.getElementById("read"); |
---|
69 | read.checked = true; |
---|
70 | read.onclick = toggleRead; |
---|
71 | var write = document.getElementById("write"); |
---|
72 | write.checked = false; |
---|
73 | write.onclick = toggleWrite; |
---|
74 | document.getElementById("clear").onclick = clearCache; |
---|
75 | var tileloadstart = document.getElementById("tileloadstart"); |
---|
76 | tileloadstart.checked = "checked"; |
---|
77 | tileloadstart.onclick = setType; |
---|
78 | document.getElementById("tileerror").onclick = setType; |
---|
79 | document.getElementById("seed").onclick = startSeeding; |
---|
80 | |
---|
81 | // detect what the browser supports |
---|
82 | function detect(evt) { |
---|
83 | // detection is only done once, so we remove the listener. |
---|
84 | evt.object.events.unregister("loadend", null, detect); |
---|
85 | var tile = map.baseLayer.grid[0][0]; |
---|
86 | try { |
---|
87 | var canvasContext = tile.getCanvasContext(); |
---|
88 | if (canvasContext) { |
---|
89 | // will throw an exception if CORS image requests are not supported |
---|
90 | canvasContext.canvas.toDataURL(); |
---|
91 | } else { |
---|
92 | status.innerHTML = "Canvas not supported. Try a different browser."; |
---|
93 | } |
---|
94 | } catch(e) { |
---|
95 | // we remove the OSM layer if CORS image requests are not supported. |
---|
96 | map.setBaseLayer(map.layers[1]); |
---|
97 | evt.object.destroy(); |
---|
98 | layerSwitcher.destroy(); |
---|
99 | } |
---|
100 | } |
---|
101 | |
---|
102 | // update the number of cache hits and detect missing CORS support |
---|
103 | function updateStatus(evt) { |
---|
104 | if (window.localStorage) { |
---|
105 | status.innerHTML = localStorage.length + " entries in cache."; |
---|
106 | } else { |
---|
107 | status.innerHTML = "Local storage not supported. Try a different browser."; |
---|
108 | } |
---|
109 | if (evt && evt.tile.url.substr(0, 5) === "data:") { |
---|
110 | cacheHits++; |
---|
111 | } |
---|
112 | hits.innerHTML = cacheHits + " cache hits."; |
---|
113 | } |
---|
114 | |
---|
115 | // turn the cacheRead controls on and off |
---|
116 | function toggleRead() { |
---|
117 | if (!this.checked) { |
---|
118 | cacheRead1.deactivate(); |
---|
119 | cacheRead2.deactivate(); |
---|
120 | } else { |
---|
121 | setType(); |
---|
122 | } |
---|
123 | } |
---|
124 | |
---|
125 | // turn the cacheWrite control on and off |
---|
126 | function toggleWrite() { |
---|
127 | cacheWrite[cacheWrite.active ? "deactivate" : "activate"](); |
---|
128 | } |
---|
129 | |
---|
130 | // clear all tiles from the cache |
---|
131 | function clearCache() { |
---|
132 | OpenLayers.Control.CacheWrite.clearCache(); |
---|
133 | updateStatus(); |
---|
134 | } |
---|
135 | |
---|
136 | // activate the cacheRead control that matches the desired fetch strategy |
---|
137 | function setType() { |
---|
138 | if (tileloadstart.checked) { |
---|
139 | cacheRead1.activate(); |
---|
140 | } else { |
---|
141 | cacheRead2.activate(); |
---|
142 | } |
---|
143 | } |
---|
144 | |
---|
145 | // start seeding the cache |
---|
146 | function startSeeding() { |
---|
147 | var layer = map.baseLayer, |
---|
148 | zoom = map.getZoom(); |
---|
149 | seeding = { |
---|
150 | zoom: zoom, |
---|
151 | extent: map.getExtent(), |
---|
152 | center: map.getCenter(), |
---|
153 | cacheWriteActive: cacheWrite.active, |
---|
154 | buffer: layer.buffer, |
---|
155 | layer: layer |
---|
156 | }; |
---|
157 | // make sure the next setCenter triggers a load |
---|
158 | map.zoomTo(zoom === layer.numZoomLevels-1 ? zoom - 1 : zoom + 1); |
---|
159 | // turn on cache writing |
---|
160 | cacheWrite.activate(); |
---|
161 | // turn off cache reading |
---|
162 | cacheRead1.deactivate(); |
---|
163 | cacheRead2.deactivate(); |
---|
164 | |
---|
165 | layer.events.register("loadend", null, seed); |
---|
166 | |
---|
167 | // start seeding |
---|
168 | map.setCenter(seeding.center, zoom); |
---|
169 | } |
---|
170 | |
---|
171 | // seed a zoom level based on the extent at the time startSeeding was called |
---|
172 | function seed() { |
---|
173 | var layer = seeding.layer; |
---|
174 | var tileWidth = layer.tileSize.w; |
---|
175 | var nextZoom = map.getZoom() + 1; |
---|
176 | var extentWidth = seeding.extent.getWidth() / map.getResolutionForZoom(nextZoom); |
---|
177 | // adjust the layer's buffer size so we don't have to pan |
---|
178 | layer.buffer = Math.ceil((extentWidth / tileWidth - map.getSize().w / tileWidth) / 2); |
---|
179 | map.zoomIn(); |
---|
180 | if (nextZoom === layer.numZoomLevels-1) { |
---|
181 | stopSeeding(); |
---|
182 | } |
---|
183 | } |
---|
184 | |
---|
185 | // stop seeding (when done or when cache is full) |
---|
186 | function stopSeeding() { |
---|
187 | // we're done - restore previous settings |
---|
188 | seeding.layer.events.unregister("loadend", null, seed); |
---|
189 | seeding.layer.buffer = seeding.buffer; |
---|
190 | map.setCenter(seeding.center, seeding.zoom); |
---|
191 | if (!seeding.cacheWriteActive) { |
---|
192 | cacheWrite.deactivate(); |
---|
193 | } |
---|
194 | if (read.checked) { |
---|
195 | setType(); |
---|
196 | } |
---|
197 | seeding = false; |
---|
198 | } |
---|
199 | } |
---|