Resize Google Maps on Duels Game Breakdown pages from 1.00x to 1.50x magnification
// ==UserScript==
// @name Geoguessr Result Map Resizer
// @name:ja Geoguessr Result Map Resizer
// @namespace https://greasyfork.org/ja/users/1492018-sino87
// @version 1.00
// @description Resize Google Maps on Duels Game Breakdown pages from 1.00x to 1.50x magnification
// @description:ja DuelsのGame BreakdownページにあるGoogleマップのサイズを1.00倍から1.50倍まで調整可能
// @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
// @match https://www.geoguessr.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const SCALE_STORAGE_KEY = "geoguessrMapScale";
const POSITION_STORAGE_KEY = "geoguessrMapPanelPosition";
let currentScale = parseFloat(localStorage.getItem(SCALE_STORAGE_KEY)) || 1.00;
let panelPosition = JSON.parse(localStorage.getItem(POSITION_STORAGE_KEY)) || { top: 80, left: 20 };
const fontStyle = document.createElement('style');
fontStyle.textContent = `@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@600&display=swap');`;
document.head.appendChild(fontStyle);
function resizeMap() {
const mapElement = document.querySelector('div.game-summary_mapContainer__iYGL5');
if (!mapElement) return;
if (!mapElement.dataset.originalHeight) {
mapElement.dataset.originalHeight = mapElement.offsetHeight + '';
}
const originalHeight = parseFloat(mapElement.dataset.originalHeight);
const newHeight = originalHeight * currentScale;
mapElement.style.height = newHeight + 'px';
}
function initializeMapResize() {
const mapElement = document.querySelector('div.game-summary_mapContainer__iYGL5');
if (mapElement && !mapElement.dataset.originalHeight) {
const height = mapElement.offsetHeight;
if (height > 0) {
mapElement.dataset.originalHeight = height + '';
resizeMap();
}
}
}
function createPanel() {
const existingPanel = document.getElementById('map-scale-panel');
if (existingPanel) {
existingPanel.remove();
}
const panel = document.createElement('div');
panel.id = 'map-scale-panel';
panel.style.cssText = `
position: fixed;
top: ${panelPosition.top}px;
left: ${panelPosition.left}px;
width: 180px;
height: 90px;
background: rgba(15, 15, 15, 0.7);
color: white;
border-radius: 8px;
padding: 10px;
z-index: 9999;
font-family: 'Noto Sans', sans-serif;
font-weight: 600;
font-size: 16px;
cursor: move;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
`;
const title = document.createElement('div');
title.textContent = 'Map Resizer';
title.style.textAlign = 'center';
const sliderContainer = document.createElement('div');
sliderContainer.style.cssText = `
width: 100%;
display: flex;
justify-content: center;
`;
const slider = document.createElement('input');
slider.type = 'range';
slider.min = '0';
slider.max = '100';
slider.value = ((currentScale - 1.00) / 0.50) * 100;
slider.style.cssText = `
width: 100%;
appearance: none;
height: 0.4rem;
margin: 0;
border: 1px solid gray;
border-radius: 0.4rem;
padding: 0;
background-color: black;
`;
const sliderStyle = document.createElement('style');
sliderStyle.textContent = `
#map-scale-panel input[type="range"]::-webkit-slider-runnable-track {
margin: 0 -5px;
}
#map-scale-panel input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: #7d8cff;
cursor: pointer;
border: 1px solid white;
}
`;
document.head.appendChild(sliderStyle);
const scaleDisplay = document.createElement('div');
scaleDisplay.textContent = '×' + currentScale.toFixed(2);
scaleDisplay.style.textAlign = 'center';
slider.addEventListener('input', function(e) {
const sliderValue = parseFloat(e.target.value);
// 進捗背景を動的に更新
const ratio = sliderValue;
this.style.background = `linear-gradient(90deg, #7d8cff ${ratio}%, #000000 ${ratio}%)`;
currentScale = 1.00 + (sliderValue / 100) * 0.50;
scaleDisplay.textContent = '×' + currentScale.toFixed(2);
localStorage.setItem(SCALE_STORAGE_KEY, currentScale);
resizeMap();
});
let isDragging = false;
let dragOffset = { x: 0, y: 0 };
title.addEventListener('mousedown', function(e) {
isDragging = true;
dragOffset.x = e.clientX - panel.offsetLeft;
dragOffset.y = e.clientY - panel.offsetTop;
e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (isDragging) {
// 画面の境界を取得
const maxX = window.innerWidth - panel.offsetWidth;
const maxY = window.innerHeight - panel.offsetHeight;
// 新しい位置を計算
let newX = e.clientX - dragOffset.x;
let newY = e.clientY - dragOffset.y;
// 境界内に制限
newX = Math.max(0, Math.min(newX, maxX));
newY = Math.max(0, Math.min(newY, maxY));
panel.style.left = newX + 'px';
panel.style.top = newY + 'px';
}
});
document.addEventListener('mouseup', function() {
if (isDragging) {
isDragging = false;
panelPosition = {
top: parseInt(panel.style.top),
left: parseInt(panel.style.left)
};
localStorage.setItem(POSITION_STORAGE_KEY, JSON.stringify(panelPosition));
}
});
sliderContainer.appendChild(slider);
panel.appendChild(title);
panel.appendChild(sliderContainer);
panel.appendChild(scaleDisplay);
document.body.appendChild(panel);
}
let lastUrl = window.location.href;
function checkForUrlChange() {
const currentUrl = window.location.href;
if (currentUrl !== lastUrl) {
lastUrl = currentUrl;
handlePageChange();
}
}
function handlePageChange() {
const isDuelsResultPage = /^https:\/\/www\.geoguessr\.com(\/[^/]+)?\/duels\/[^/]+\/summary$/.test(window.location.href);
if (isDuelsResultPage) {
setTimeout(() => {
initializeMapResize();
createPanel();
}, 1000);
} else {
const panel = document.getElementById('map-scale-panel');
if (panel) {
panel.remove();
}
}
}
setInterval(checkForUrlChange, 500);
handlePageChange();
})();