Smooth scroll geoguessr map

Makes the leaflet map in openguessr scroll more smoothly

// ==UserScript==
// @name        Smooth scroll geoguessr map
// @match       https://openguessr.com/*
// @grant       none
// @version     1.0
// @author      ItsPi3141
// @description Makes the leaflet map in openguessr scroll more smoothly
// @run-at      document-start
// @license     MIT
// @namespace https://greasyfork.org/users/1334015
// ==/UserScript==

let injected = false;
const originalFunctionCall = Function.prototype.call;
Function.prototype.call = function (...args) {
	if (!injected && args[0]?._leaflet_id) {
		inject();
		applyStyles();
		injected = true;
	}

	return originalFunctionCall.apply(this, args);
};

// https://github.com/mutsuyuki/Leaflet.SmoothWheelZoom
const inject = () => {
	L.Map.mergeOptions({
		scrollWheelZoom: false,
		smoothWheelZoom: true,
		smoothSensitivity: 2,
	});

	L.Map.SmoothWheelZoom = L.Handler.extend({
		addHooks: function () {
			L.DomEvent.on(this._map._container, "wheel", this._onWheelScroll, this);
		},

		removeHooks: function () {
			L.DomEvent.off(this._map._container, "wheel", this._onWheelScroll, this);
		},

		_onWheelScroll: function (e) {
			if (!this._isWheeling) {
				this._onWheelStart(e);
			}
			this._onWheeling(e);
		},

		_onWheelStart: function (e) {
			var map = this._map;
			this._isWheeling = true;
			this._wheelMousePosition = map.mouseEventToContainerPoint(e);
			this._centerPoint = map.getSize()._divideBy(2);
			this._startLatLng = map.containerPointToLatLng(this._centerPoint);
			this._wheelStartLatLng = map.containerPointToLatLng(
				this._wheelMousePosition,
			);
			this._startZoom = map.getZoom();
			this._moved = false;
			this._zooming = true;

			map._stop();
			if (map._panAnim) map._panAnim.stop();

			this._goalZoom = map.getZoom();
			this._prevCenter = map.getCenter();
			this._prevZoom = map.getZoom();

			this._zoomAnimationId = requestAnimationFrame(
				this._updateWheelZoom.bind(this),
			);
		},

		_onWheeling: function (e) {
			var map = this._map;

			this._goalZoom =
				this._goalZoom +
				L.DomEvent.getWheelDelta(e) * 0.003 * map.options.smoothSensitivity;
			if (
				this._goalZoom < map.getMinZoom() ||
				this._goalZoom > map.getMaxZoom()
			) {
				this._goalZoom = map._limitZoom(this._goalZoom);
			}
			this._wheelMousePosition = this._map.mouseEventToContainerPoint(e);

			clearTimeout(this._timeoutId);
			this._timeoutId = setTimeout(this._onWheelEnd.bind(this), 200);

			L.DomEvent.preventDefault(e);
			L.DomEvent.stopPropagation(e);
		},

		_onWheelEnd: function (e) {
			this._isWheeling = false;
			cancelAnimationFrame(this._zoomAnimationId);
			this._map._moveEnd(true);
		},

		_updateWheelZoom: function () {
			var map = this._map;

			if (
				!map.getCenter().equals(this._prevCenter) ||
				map.getZoom() != this._prevZoom
			)
				return;

			this._zoom = map.getZoom() + (this._goalZoom - map.getZoom()) * 0.3;
			this._zoom = Math.floor(this._zoom * 100) / 100;

			var delta = this._wheelMousePosition.subtract(this._centerPoint);
			if (delta.x === 0 && delta.y === 0) return;

			if (map.options.smoothWheelZoom === "center") {
				this._center = this._startLatLng;
			} else {
				this._center = map.unproject(
					map.project(this._wheelStartLatLng, this._zoom).subtract(delta),
					this._zoom,
				);
			}

			if (!this._moved) {
				map._moveStart(true, false);
				this._moved = true;
			}

			map._move(this._center, this._zoom);
			this._prevCenter = map.getCenter();
			this._prevZoom = map.getZoom();

			this._zoomAnimationId = requestAnimationFrame(
				this._updateWheelZoom.bind(this),
			);
		},
	});

	L.Map.addInitHook("addHandler", "smoothWheelZoom", L.Map.SmoothWheelZoom);
};

const applyStyles = () => {
	const styles = document.createElement("style");
	styles.innerHTML = `.leaflet-zoom-animated {
    transition: 0.1s transform ease-out;
  }
  .leaflet-layer :is([style*='z-index: 17']) {
    opacity: 0 !important;
  }`;
	document.head.appendChild(styles);
};