├── LICENSE ├── README.md ├── index.html └── StreetViewButtons.js /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Street View Buttons 2 | 3 | This is a simple plugin for [Leaflet](http://leafletjs.com) that shows a row of buttons. 4 | When you click any of these buttons, a new window or tab is opened, with a street view 5 | focused on the centre of the map. Just do: 6 | 7 | L.streetView().addTo(map); 8 | 9 | Check out [a demo here](https://zverik.github.io/leaflet-streetview/index.html). 10 | 11 | If you need to specify the focus point, instead of it being in the centre, use 12 | `fixCoord(latlon)` method, and `releaseCoord()` to continue tracking the map. 13 | 14 | Providers currently supported: 15 | 16 | * Google Street View 17 | * Bing StreetSide 18 | * Yandex Panoramas (for Russia and neighbouring countries) 19 | * MosAtlas (for Moscow, Russia) 20 | * Mapillary 21 | * OpenStreetCam 22 | 23 | Please make a pull request if you know an URL template for another provider. 24 | 25 | ## License and Author 26 | 27 | Written by Ilya Zverev, published under WTFPL: do what you want with it. 28 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Street View Providers Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /StreetViewButtons.js: -------------------------------------------------------------------------------- 1 | L.StreetView = L.Control.extend({ 2 | options: { 3 | google: true, 4 | bing: true, 5 | yandex: true, 6 | mapillary: true, 7 | mapillaryId: null, 8 | openstreetcam: true, 9 | mosatlas: true 10 | }, 11 | 12 | providers: [ 13 | ['google', 'GSV', 'Google Street View', false, 14 | 'https://www.google.com/maps?layer=c&cbll={lat},{lon}'], 15 | ['bing', 'Bing', 'Bing StreetSide', 16 | L.latLngBounds([[25, -168], [71.4, 8.8]]), 17 | 'https://www.bing.com/maps?cp={lat}~{lon}&lvl=19&style=x&v=2'], 18 | ['yandex', 'ЯП', 'Yandex Panoramas', 19 | L.latLngBounds([[35.6, 18.5], [72, 180]]), 20 | 'https://yandex.ru/maps/?panorama%5Bpoint%5D={lon},{lat}'], 21 | ['mapillary', 'Mplr', 'Mapillary Photos', false, 22 | 'https://a.mapillary.com/v3/images?client_id={id}&closeto={lon},{lat}&lookat={lon},{lat}'], 23 | ['openstreetcam', 'OSC', 'OpenStreetCam', false, 24 | 'lat={lat}&lng={lon}&distance=50'], 25 | ['mosatlas', 'Мос', 'Панорамы из Атласа Москвы', 26 | L.latLngBounds([[55.113, 36.708], [56.041, 38]]), 27 | 'http://atlas.mos.ru/?lang=ru&z=9&ll={lon}%2C{lat}&pp={lon}%2C{lat}'], 28 | ], 29 | 30 | onAdd: function(map) { 31 | this._container = L.DomUtil.create('div', 'leaflet-bar'); 32 | this._buttons = []; 33 | 34 | for (var i = 0; i < this.providers.length; i++) 35 | this._addProvider(this.providers[i]); 36 | 37 | map.on('moveend', function() { 38 | if (!this._fixed) 39 | this._update(map.getCenter()); 40 | }, this); 41 | this._update(map.getCenter()); 42 | return this._container; 43 | }, 44 | 45 | fixCoord: function(latlon) { 46 | this._update(latlon); 47 | this._fixed = true; 48 | }, 49 | 50 | releaseCoord: function() { 51 | this._fixed = false; 52 | this._update(this._map.getCenter()); 53 | }, 54 | 55 | _addProvider: function(provider) { 56 | if (!this.options[provider[0]]) 57 | return; 58 | if (provider[0] == 'mapillary' && !this.options.mapillaryId) 59 | return; 60 | var button = L.DomUtil.create('a'); 61 | button.innerHTML = provider[1]; 62 | button.title = provider[2]; 63 | button._bounds = provider[3]; 64 | button._template = provider[4]; 65 | button.href = '#'; 66 | button.target = 'streetview'; 67 | button.style.padding = '0 8px'; 68 | button.style.width = 'auto'; 69 | 70 | // Some buttons require complex logic 71 | if (provider[0] == 'mapillary') { 72 | button._needUrl = false; 73 | L.DomEvent.on(button, 'click', function(e) { 74 | if (button._href) { 75 | this._ajaxRequest( 76 | button._href.replace(/{id}/, this.options.mapillaryId), 77 | function(data) { 78 | if (data && data.features && data.features[0].properties) { 79 | var photoKey = data.features[0].properties.key, 80 | url = 'https://www.mapillary.com/map/im/{key}'.replace(/{key}/, photoKey); 81 | window.open(url, button.target); 82 | } 83 | } 84 | ); 85 | } 86 | return L.DomEvent.preventDefault(e); 87 | }, this); 88 | } else if (provider[0] == 'openstreetcam') { 89 | button._needUrl = false; 90 | L.DomEvent.on(button, 'click', function(e) { 91 | if (button._href) { 92 | this._ajaxRequest( 93 | 'http://openstreetcam.org/nearby-tracks', 94 | function(data) { 95 | if (data && data.osv && data.osv.sequences) { 96 | var seq = data.osv.sequences[0], 97 | url = 'https://www.openstreetcam.org/details/'+seq.sequence_id+'/'+seq.sequence_index; 98 | window.open(url, button.target); 99 | } 100 | }, 101 | button._href 102 | ); 103 | } 104 | return L.DomEvent.preventDefault(e); 105 | }, this); 106 | } else 107 | button._needUrl = true; 108 | 109 | // Overriding some of the leaflet styles 110 | button.style.display = 'inline-block'; 111 | button.style.border = 'none'; 112 | button.style.borderRadius = '0 0 0 0'; 113 | this._buttons.push(button); 114 | }, 115 | 116 | _update: function(center) { 117 | if (!center) 118 | return; 119 | var last; 120 | for (var i = 0; i < this._buttons.length; i++) { 121 | var b = this._buttons[i], 122 | show = !b._bounds || b._bounds.contains(center), 123 | vis = this._container.contains(b); 124 | 125 | if (show && !vis) { 126 | ref = last ? last.nextSibling : this._container.firstChild; 127 | this._container.insertBefore(b, ref); 128 | } else if (!show && vis) { 129 | this._container.removeChild(b); 130 | return; 131 | } 132 | last = b; 133 | 134 | var tmpl = b._template; 135 | tmpl = tmpl 136 | .replace(/{lon}/g, L.Util.formatNum(center.lng, 6)) 137 | .replace(/{lat}/g, L.Util.formatNum(center.lat, 6)); 138 | if (b._needUrl) 139 | b.href = tmpl; 140 | else 141 | b._href = tmpl; 142 | } 143 | }, 144 | 145 | _ajaxRequest: function(url, callback, post_data) { 146 | if (window.XMLHttpRequest === undefined) 147 | return; 148 | var req = new XMLHttpRequest(); 149 | req.open(post_data ? 'POST' : "GET", url); 150 | if (post_data) 151 | req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 152 | req.onreadystatechange = function() { 153 | if (req.readyState === 4 && req.status == 200) { 154 | var data = (JSON.parse(req.responseText)); 155 | callback(data); 156 | } 157 | }; 158 | req.send(post_data); 159 | } 160 | }); 161 | 162 | L.streetView = function(options) { 163 | return new L.StreetView(options); 164 | } 165 | --------------------------------------------------------------------------------