MediaWiki:Common.js: Difference between revisions
From Rise of Agon Wiki
Fix tile coords with unproject/project |
Fix tile bounds/centering to avoid negative tile requests |
||
| Line 28: | Line 28: | ||
var tileSize = 256; | var tileSize = 256; | ||
var maxZoom = 6; // 16384 / 256 = 64 => log2(64) = 6 | var maxZoom = 6; // 16384 / 256 = 64 => log2(64) = 6 | ||
var crs = L.CRS.Simple; | |||
// Create map | // Compute bounds directly from CRS (avoid map-dependent unproject) | ||
var southWest = crs.unproject(L.point(0, imageHeight), maxZoom); | |||
var northEast = crs.unproject(L.point(imageWidth, 0), maxZoom); | |||
var bounds = new L.LatLngBounds(southWest, northEast); | |||
// Create map centered on bounds to avoid negative tile lookups | |||
var map = L.map('agon-map-container', { | var map = L.map('agon-map-container', { | ||
crs: | crs: crs, | ||
minZoom: 0, | minZoom: 0, | ||
maxZoom: maxZoom, | maxZoom: maxZoom, | ||
zoom: 0 | center: bounds.getCenter(), | ||
zoom: 2, | |||
maxBounds: bounds, | |||
maxBoundsViscosity: 1.0 | |||
}); | }); | ||
// Tile layer using generated pyramid under /resources/assets/tiles/AgonBigMap/{z}/{x}/{y}.jpg | // Tile layer using generated pyramid under /resources/assets/tiles/AgonBigMap/{z}/{x}/{y}.jpg | ||
| Line 53: | Line 57: | ||
}).addTo(map); | }).addTo(map); | ||
// Fit map to bounds | // Fit map to bounds | ||
map.fitBounds(bounds); | map.fitBounds(bounds); | ||
// Add scale | // Add scale | ||
Revision as of 09:05, 25 January 2026
// Custom Agon World Map with Leaflet (tiled)
(function() {
// Only run on map pages
if (!document.getElementById('agon-map-container')) return;
// Load Leaflet CSS
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
document.head.appendChild(link);
// Load Leaflet JS
var script = document.createElement('script');
script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
script.onload = function() {
initAgonMap();
};
document.head.appendChild(script);
})();
function initAgonMap() {
var mapContainer = document.getElementById('agon-map-container');
if (!mapContainer) return;
// Image dimensions and tiling
var imageWidth = 16384;
var imageHeight = 16384;
var tileSize = 256;
var maxZoom = 6; // 16384 / 256 = 64 => log2(64) = 6
var crs = L.CRS.Simple;
// Compute bounds directly from CRS (avoid map-dependent unproject)
var southWest = crs.unproject(L.point(0, imageHeight), maxZoom);
var northEast = crs.unproject(L.point(imageWidth, 0), maxZoom);
var bounds = new L.LatLngBounds(southWest, northEast);
// Create map centered on bounds to avoid negative tile lookups
var map = L.map('agon-map-container', {
crs: crs,
minZoom: 0,
maxZoom: maxZoom,
center: bounds.getCenter(),
zoom: 2,
maxBounds: bounds,
maxBoundsViscosity: 1.0
});
// Tile layer using generated pyramid under /resources/assets/tiles/AgonBigMap/{z}/{x}/{y}.jpg
var tileUrl = mw.config.get('wgScriptPath') + '/resources/assets/tiles/AgonBigMap/{z}/{x}/{y}.jpg';
L.tileLayer(tileUrl, {
tileSize: tileSize,
minZoom: 0,
maxZoom: maxZoom,
maxNativeZoom: maxZoom,
bounds: bounds,
noWrap: true
}).addTo(map);
// Fit map to bounds
map.fitBounds(bounds);
// Add scale
L.control.scale().addTo(map);
// Click to get coordinates (report image pixel coords Y, X)
map.on('click', function(e) {
var point = map.project(e.latlng, maxZoom); // pixel space
var y = point.y.toFixed(2);
var x = point.x.toFixed(2);
var text = 'Coordinates: ' + y + ', ' + x;
console.log(text);
L.popup()
.setLatLng(e.latlng)
.setContent(text)
.openOn(map);
});
// Load markers from page data; stored as 'Y, X' pixel coordinates
if (window.agonMapMarkers) {
window.agonMapMarkers.forEach(function(marker) {
var coords = marker.coordinates.split(',').map(parseFloat); // [Y, X]
var latlng = map.unproject([coords[1], coords[0]], maxZoom); // [x, y]
var icon = L.icon({
iconUrl: marker.icon || mw.config.get('wgScriptPath') + '/resources/assets/marker-icon.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34]
});
L.marker(latlng, { icon: icon })
.addTo(map)
.bindPopup('<b>' + marker.name + '</b><br>' + marker.description);
});
}
}
