├── 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 |
--------------------------------------------------------------------------------