Open Layers - Working Example

setting up a map using open layers. load a group layer of base layers and allow for switching baselayer with radio input. also has external zoom & rotation.

HTML

<script src="https://cdn.jsdelivr.net/npm/ol@v7.2.2/dist/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.2.2/ol.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<button onclick="duplicateMap()">Copy Map</button>

<div id="mapBox">
	<div id="map" class="map"></div>
	<div id="rotationContainer">
		0 <input id="rotationSlider" type="range" min="0" max="360" value="0"> 360
		<br>
	</div>
	<input id="zoomSlider" type="range" orient="vertical" min="10" max="18" value="13" />
</div>
<div id="mapCopy"></div>

<div id="baseMapSelect">
  <h4 style="margin:0px; text-decoration: underline;">Select your map style</h4>
</div>

CSS

button{margin: 10px 0}
#mapBox{
	position: absolute;
	width: 40%;
}

#map {
  width: 300px;
  height: 300px;
	border: 2px solid black;
}
#mapCopy{
	position:absolute;
	top: 50px;
	left: 450px;
	width: 40%;
	float: right;
}

#baseMapSelect {
	position: relative;
  top: 330px;
}

input[type=range][orient="vertical"] {
  writing-mode: bt-lr;
  /* IE */
  -webkit-appearance: slider-vertical;
  /* Chromium */
  width: 8px;
  min-height: 175px;
  padding: 0 5px;
}

#zoomSlider {
  position: absolute;
	top: 0px;
  left: 315px;
  height: 280px;
  margin: 10px;
}

#rotationContainer{
	position: relative;
	left: 5px;
}

JavaScript

window.onload = init;

// set some variables
var selectedBaseMap = "OSMStandard";
var currentLonLat = [-63.5859487, 44.648618]; //Halifax Lon/Lat
var defaultZoom = 12;
var defaultRotation = 0;
var rotationSlider = document.getElementById("rotationSlider");
var zoomSlider = document.getElementById("zoomSlider");

mapCenter = ol.proj.fromLonLat(currentLonLat); //Converts Lon/Lat to center

function init() {
  // setup the map
  const map = new ol.Map({
    view: new ol.View({
      center: mapCenter,
      zoom: defaultZoom,
      rotation: defaultRotation,
    }),
    target: "map",
  });

  // ROTATION //
  rotationSlider.oninput = function () {
    map.getView().setRotation(degreesToRads(this.value));
  };
  // ZOOM //
  zoomSlider.oninput = function () {
    map.getView().setZoom(this.value);
  };

  map.getView().on("change:rotation", function (event) {
    deg = radsToDegrees(event.target.getRotation());
    console.log(deg);
    if (deg > 360) {
      deg = deg - 360;
    }
    rotationSlider.value = deg;
  });

  /* Base Map Layer */
  const openStreetMapStandard = new ol.layer.Tile({
    source: new ol.source.OSM(),
    visible: true,
    title: "OSMStandard",
  });
  const openStreetMapHumanitarian = new ol.layer.Tile({
    source: new ol.source.OSM({
      url: "https://{a-c}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
    }),
    visible: false,
    title: "OSMHumanitarian",
  });
  const stamenToner = new ol.layer.Tile({
    source: new ol.source.XYZ({
      url: "https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png",
      crossOrigin: 'anonymous',
      attributions:
        'Map tiles by <a href="http://stamen.com">Stamen Design</a>, \
						under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. \
						Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.',
    }),
    visible: false,
    title: "StamenToner",
  });
  const stamenTerrain = new...