PageSourceSearch

https://reviewswales.wales/dist/libraries/proj4/proj4leaflet.js

js reviewswales.wales collected 2026-10-08 06:13:59 UTC 7,163 bytes, 263 lines download raw bytes

1(function (factory) {
2	var L, proj4;
3	if (typeof define === 'function' && define.amd) {
4		// AMD
5		define(['leaflet', 'proj4'], factory);
6	} else if (typeof module === 'object' && typeof module.exports === "object") {
7		// Node/CommonJS
8		L = require('leaflet');
9		proj4 = require('proj4');
10		module.exports = factory(L, proj4);
11	} else {
12		// Browser globals
13		if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
14			throw 'Leaflet and proj4 must be loaded first';
15		factory(window.L, window.proj4);
16	}
17}(function (L, proj4) {
18
19	L.Proj = {};
20
21	L.Proj._isProj4Obj = function(a) {
22		return (typeof a.inverse !== 'undefined' &&
23			typeof a.forward !== 'undefined');
24	};
25
26	L.Proj.Projection = L.Class.extend({
27		initialize: function(code, def, bounds) {
28			var isP4 = L.Proj._isProj4Obj(code);
29			this._proj = isP4 ? code : this._projFromCodeDef(code, def);
30			this.bounds = isP4 ? def : bounds;
31		},
32
33		project: function (latlng) {
34			var point = this._proj.forward([latlng.lng, latlng.lat]);
35			return new L.Point(point[0], point[1]);
36		},
37
38		unproject: function (point, unbounded) {
39			var point2 = this._proj.inverse([point.x, point.y]);
40			return new L.LatLng(point2[1], point2[0], unbounded);
41		},
42
43		_projFromCodeDef: function(code, def) {
44			if (def) {
45				proj4.defs(code, def);
46			} else if (proj4.defs[code] === undefined) {
47				var urn = code.split(':');
48				if (urn.length > 3) {
49					code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
50				}
51				if (proj4.defs[code] === undefined) {
52					throw 'No projection definition for code ' + code;
53				}
54			}
55
56			return proj4(code);
57		}
58	});
59
60	L.Proj.CRS = L.Class.extend({
61		includes: L.CRS,
62
63		options: {
64			transformation: new L.Transformation(1, 0, -1, 0)
65		},
66
67		initialize: function(a, b, c) {
68			var code,
69			    proj,
70			    def,
71			    options;
72
73			if (L.Proj._isProj4Obj(a)) {
74				proj = a;
75				code = proj.srsCode;
76				options = b || {};
77
78				this.projection = new L.Proj.Projection(proj, options.bounds);
79			} else {
80				code = a;
81				def = b;
82				options = c || {};
83				this.projection = new L.Proj.Projection(code, def, options.bounds);
84			}
85
86			L.Util.setOptions(this, options);
87			this.code = code;
88			this.transformation = this.options.transformation;
89
90			if (this.options.origin) {
91				this.transformation =
92					new L.Transformation(1, -this.options.origin[0],
93						-1, this.options.origin[1]);
94			}
95
96			if (this.options.scales) {
97				this._scales = this.options.scales;
98			} else if (this.options.resolutions) {
99				this._scales = [];
100				for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
101					if (this.options.resolutions[i]) {
102						this._scales[i] = 1 / this.options.resolutions[i];
103					}
104				}
105			}
106
107			this.infinite = !this.options.bounds;
108
109		},
110
111		scale: function(zoom) {
112			var iZoom = Math.floor(zoom),
113				baseScale,
114				nextScale,
115				scaleDiff,
116				zDiff;
117			if (zoom === iZoom) {
118				return this._scales[zoom];
119			} else {
120				// Non-integer zoom, interpolate
121				baseScale = this._scales[iZoom];
122				nextScale = this._scales[iZoom + 1];
123				scaleDiff = nextScale - baseScale;
124				zDiff = (zoom - iZoom);
125				return baseScale + scaleDiff * zDiff;
126			}
127		},
128
129		zoom: function(scale) {
130			// Find closest number in this._scales, down
131			var downScale = this._closestElement(this._scales, scale),
132				downZoom = this._scales.indexOf(downScale),
133				nextScale,
134				nextZoom,
135				scaleDiff;
136			// Check if scale is downScale => return array index
137			if (scale === downScale) {
138				return downZoom;
139			}
140			// Interpolate
141			nextZoom = downZoom + 1;
142			nextScale = this._scales[nextZoom];
143			if (nextScale === undefined) {
144				return Infinity;
145			}
146			scaleDiff = nextScale - downScale;
147			return (scale - downScale) / scaleDiff + downZoom;
148		},
149
150		distance: L.CRS.Earth.distance,
151
152		R: L.CRS.Earth.R,
153
154		/* Get the closest lowest element in an array */
155		_closestElement: function(array, element) {
156			var low;
157			for (var i = array.length; i--;) {
158				if (array[i] <= element && (low === undefined || low < array[i])) {
159					low = array[i];
160				}
161			}
162			return low;
163		}
164	});
165
166	L.Proj.GeoJSON = L.GeoJSON.extend({
167		initialize: function(geojson, options) {
168			this._callLevel = 0;
169			L.GeoJSON.prototype.initialize.call(this, geojson, options);
170		},
171
172		addData: function(geojson) {
173			var crs;
174
175			if (geojson) {
176				if (geojson.crs && geojson.crs.type === 'name') {
177					crs = new L.Proj.CRS(geojson.crs.properties.name);
178				} else if (geojson.crs && geojson.crs.type) {
179					crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
180				}
181
182				if (crs !== undefined) {
183					this.options.coordsToLatLng = function(coords) {
184						var point = L.point(coords[0], coords[1]);
185						return crs.projection.unproject(point);
186					};
187				}
188			}
189
190			// Base class' addData might call us recursively, but
191			// CRS shouldn't be cleared in that case, since CRS applies
192			// to the whole GeoJSON, inluding sub-features.
193			this._callLevel++;
194			try {
195				L.GeoJSON.prototype.addData.call(this, geojson);
196			} finally {
197				this._callLevel--;
198				if (this._callLevel === 0) {
199					delete this.options.coordsToLatLng;
200				}
201			}
202		}
203	});
204
205	L.Proj.geoJson = function(geojson, options) {
206		return new L.Proj.GeoJSON(geojson, options);
207	};
208
209	L.Proj.ImageOverlay = L.ImageOverlay.extend({
210		initialize: function (url, bounds, options) {
211			L.ImageOverlay.prototype.initialize.call(this, url, null, options);
212			this._projectedBounds = bounds;
213		},
214
215		// Danger ahead: Overriding internal methods in Leaflet.
216		// Decided to do this rather than making a copy of L.ImageOverlay
217		// and doing very tiny modifications to it.
218		// Future will tell if this was wise or not.
219		_animateZoom: function (event) {
220			var scale = this._map.getZoomScale(event.zoom);
221			var northWest = L.point(this._projectedBounds.min.x, this._projectedBounds.max.y);
222			var offset = this._projectedToNewLayerPoint(northWest, event.zoom, event.center);
223
224			L.DomUtil.setTransform(this._image, offset, scale);
225		},
226
227		_reset: function () {
228			var zoom = this._map.getZoom();
229			var pixelOrigin = this._map.getPixelOrigin();
230			var bounds = L.bounds(
231				this._transform(this._projectedBounds.min, zoom)._subtract(pixelOrigin),
232				this._transform(this._projectedBounds.max, zoom)._subtract(pixelOrigin)
233			);
234			var size = bounds.getSize();
235
236			L.DomUtil.setPosition(this._image, bounds.min);
237			this._image.style.width = size.x + 'px';
238			this._image.style.height = size.y + 'px';
239		},
240
241		_projectedToNewLayerPoint: function (point, zoom, center) {
242			var viewHalf = this._map.getSize()._divideBy(2);
243			var newTopLeft = this._map.project(center, zoom)._subtract(viewHalf)._round();
244			var topLeft = newTopLeft.add(this._map._getMapPanePos());
245
246			return this._transform(point, zoom)._subtract(topLeft);
247		},
248
249		_transform: function (point, zoom) {
250			var crs = this._map.options.crs;
251			var transformation = crs.transformation;
252			var scale = crs.scale(zoom);
253
254			return transformation.transform(point, scale);
255		}
256	});
257
258	L.Proj.imageOverlay = function (url, bounds, options) {
259		return new L.Proj.ImageOverlay(url, bounds, options);
260	};
261
262	return L.Proj;
263}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.