Thanks. Including a CRS on the layer does not work and results in tile errors. It seems that Leaflet will not allow two CRSs unlike OpenLayers. I tried a different approach by recreating the map as below which seems to work. The transformation function is not needed since whilst the map is in 27700 Leaflet still works in 3857 for markers, lines etc.
<!DOCTYPE html>
<html>
<head>
<title>OS Leaflet Demo Leaflet Dual Coordinate Systems</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.6.2/proj4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4leaflet/1.0.2/proj4leaflet.min.js"></script>
<style>
#toggleButton {
position: absolute;
top: 10px;
right: 10px;
z-index: 1000;
background-color: white;
border: 2px solid black;
padding: 10px;
cursor: pointer;
font-size: 16px;
box-shadow: 0 0 3px rgba(0,0,0,0.4);
}
</style>
</head>
<body>
<div id="map" style="width: 100%; height: 600px;"></div>
<div id="toggleButton">Switch CRS</div>
<script>
var map, currentCRS = 'EPSG:3857';
// Define the EPSG:27700 projection
proj4.defs("EPSG:27700", "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs");
// Define the EPSG:27700 (British National Grid) projection using proj4
const crs27700 = new L.Proj.CRS('EPSG:27700', '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs', {
resolutions: [ 896.0, 448.0, 224.0, 112.0, 56.0, 28.0, 14.0, 7.0, 3.5, 1.75 ],
origin: [ -238375.0, 1376256.0 ],
bounds: L.bounds([0, 0], [700000, 1300000])
});
function createMap(center, zoom) {
if (currentCRS === 'EPSG:3857') {
zoom = zoom + 7;
map = L.map('map').setView(center, zoom);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
} else {
map.options.crs = crs27700;
map = L.map('map', {
center: center,
zoom: zoom -7,
maxZoom: 19,
crs: crs27700
});
L.tileLayer(
"https://api.os.uk/maps/raster/v1/zxy/Leisure_27700/{z}/{x}/{y}.png?key=API_KEY",
{
maxZoom: 10,
attribution: '© Ordnance Survey'
}
).addTo(map);
}
}
function transformCoordinates(latlng, fromCRS, toCRS) {
console.log('Transforming coordinates:', latlng, 'from', fromCRS, 'to', toCRS);
var point = proj4(fromCRS, toCRS, [latlng.lng, latlng.lat]);
console.log('Transformed coordinates:', point);
if (isFinite(point[0]) && isFinite(point[1])) {
return L.latLng(point[1], point[0]);
} else {
console.error('Transformed coordinates are not finite:', point);
return null;
}
}
document.getElementById('toggleButton').addEventListener('click', function() {
var center, zoom;
if (currentCRS === 'EPSG:3857') {
center = map.getCenter();
zoom = map.getZoom();
map.remove();
currentCRS = 'EPSG:27700';
center27700 = center;
//var center27700 = transformCoordinates(center, 'EPSG:4326', 'EPSG:27700');
//var center27700 = transformCoordinates(center, 'EPSG:4326', 'EPSG:4326');
if (center27700) {
createMap(center27700, zoom);
} else {
console.error('Failed to transform coordinates to EPSG:27700');
}
} else {
center = map.getCenter();
zoom = map.getZoom();
map.remove();
currentCRS = 'EPSG:3857';
center3857 = center;
//var center3857 = transformCoordinates(center, 'EPSG:27700', 'EPSG:4326');
if (center3857) {
createMap(center3857, zoom);
} else {
console.error('Failed to transform coordinates to EPSG:4326');
}
}
});
// Initialize the map in EPSG:3857
createMap([51.505, -0.09], 8);
</script>
</body>
</html>