Google Earth Web Compass

Google Earth Compass

// ==UserScript==
// @name         Google Earth Web Compass
// @name:tr      Google Earth Web Pusula
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Google Earth Compass
// @description:tr Google Earth Compass
// @author       davidoff26
// @match        https://earth.google.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

/* MIT License
 * 
 * Copyright (c) 2025 davidoff26
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

(function() {
    'use strict';

    // Pusula elementini oluştur
    function createCompass() {
        const compass = document.createElement('div');
        compass.id = 'ge-compass';
        compass.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 120px;
            height: 120px;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 50%;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            font-family: Arial, sans-serif;
            z-index: 9999;
            cursor: move;
            user-select: none;
            transition: background 0.3s;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
        `;

        // Hover efekti
        compass.addEventListener('mouseenter', () => {
            compass.style.background = 'rgba(0, 0, 0, 0.8)';
        });
        compass.addEventListener('mouseleave', () => {
            compass.style.background = 'rgba(0, 0, 0, 0.7)';
        });

        // Dış çember (yön harfleri için)
        const outerRing = document.createElement('div');
        outerRing.style.cssText = `
            position: absolute;
            width: 100%;
            height: 100%;
            border-radius: 50%;
        `;

        // Yön harflerinin pozisyonlarını ve stillerini ayarla
        const directions = [
            { text: 'N', angle: 0, top: '5px', left: '50%' },
            { text: 'E', angle: 90, top: '50%', right: '5px' },
            { text: 'S', angle: 180, bottom: '5px', left: '50%' },
            { text: 'W', angle: 270, top: '50%', left: '5px' }
        ];

        directions.forEach(dir => {
            const direction = document.createElement('div');
            direction.textContent = dir.text;
            direction.style.cssText = `
                position: absolute;
                font-size: 14px;
                font-weight: bold;
                transform: translate(-50%, -50%);
                color: white;
                text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
            `;

            // Pozisyonları ayarla
            if (dir.top) direction.style.top = dir.top;
            if (dir.bottom) direction.style.bottom = dir.bottom;
            if (dir.left) direction.style.left = dir.left;
            if (dir.right) direction.style.right = dir.right;

            outerRing.appendChild(direction);
        });

        // İbre - KIRMIZI-BEYAZ OLARAK DÜZELTİLDİ
        const needleContainer = document.createElement('div');
        needleContainer.id = 'ge-compass-needle-container';
        needleContainer.style.cssText = `
            position: absolute;
            width: 4px;
            height: 50px;
            transform-origin: bottom center;
            top: 15px;
            transition: transform 0.3s ease-out;
        `;

        // Kırmızı üst kısım
        const redPart = document.createElement('div');
        redPart.style.cssText = `
            width: 100%;
            height: 50%;
            background-color: red;
        `;

        // Beyaz alt kısım
        const whitePart = document.createElement('div');
        whitePart.style.cssText = `
            width: 100%;
            height: 50%;
            background-color: white;
        `;

        needleContainer.appendChild(redPart);
        needleContainer.appendChild(whitePart);

        // Derece göstergesi
        const degree = document.createElement('div');
        degree.id = 'ge-compass-degree';
        degree.style.cssText = `
            position: absolute;
            bottom: 35px;
            font-size: 16px;
            font-weight: bold;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
            background: rgba(0, 0, 0, 0.5);
            padding: 2px 6px;
            border-radius: 10px;
            transform: translateX(-50%);
            left: 50%;
        `;
        degree.textContent = '0°';

        compass.appendChild(outerRing);
        compass.appendChild(needleContainer);
        compass.appendChild(degree);
        document.body.appendChild(compass);

        // Sürüklenebilirlik için gerekli değişkenler
        let isDragging = false;
        let currentX;
        let currentY;
        let initialX;
        let initialY;

        // Sürükleme fonksiyonları
        compass.addEventListener('mousedown', dragStart);
        document.addEventListener('mousemove', drag);
        document.addEventListener('mouseup', dragEnd);

        function dragStart(e) {
            initialX = e.clientX - compass.offsetLeft;
            initialY = e.clientY - compass.offsetTop;
            isDragging = true;
        }

        function drag(e) {
            if (isDragging) {
                e.preventDefault();
                currentX = e.clientX - initialX;
                currentY = e.clientY - initialY;

                // Ekran sınırları içinde tutma
                const maxX = window.innerWidth - compass.offsetWidth;
                const maxY = window.innerHeight - compass.offsetHeight;

                currentX = Math.max(0, Math.min(currentX, maxX));
                currentY = Math.max(0, Math.min(currentY, maxY));

                compass.style.left = currentX + 'px';
                compass.style.top = currentY + 'px';
                compass.style.right = 'auto';
                compass.style.bottom = 'auto';
            }
        }

        function dragEnd() {
            isDragging = false;
        }

        return {
            needle: needleContainer,
            degree,
            compass
        };
    }

    // URL'den açı değerini çıkar
    function extractAngleFromUrl(url) {
        // Yeni regex ile negatif değerleri de algıla: -0h veya 35y gibi
        const match = url.match(/([-]?\d+\.?\d*)h/);
        return match ? parseFloat(match[1]) : 0;
    }

    // Kamera açısını izle ve pusulayı güncelle
    function watchCameraAngle() {
        const { needle, degree, compass } = createCompass();
        let lastAngle = 0;

        // URL değişikliklerini izle
        let lastUrl = '';

        // İlk yükleme
        updateCompass();

        setInterval(() => {
            const currentUrl = window.location.href;
            if (currentUrl !== lastUrl) {
                lastUrl = currentUrl;
                updateCompass();
            }
        }, 100);

        // History API'sini dinle
        const pushState = history.pushState;
        history.pushState = function() {
            pushState.apply(history, arguments);
            updateCompass();
        };

        // PopState eventi için listener ekle
        window.addEventListener('popstate', updateCompass);

        function updateCompass() {
            const newAngle = extractAngleFromUrl(window.location.href);
            
            // Açı değişimini en kısa yoldan yap
            let angleDiff = newAngle - lastAngle;
            if (Math.abs(angleDiff) > 180) {
                angleDiff = angleDiff > 0 ? angleDiff - 360 : angleDiff + 360;
            }
            lastAngle = newAngle;

            // Pusula iğnesini döndür
            needle.style.transform = `rotate(${newAngle}deg)`;
            
            // Dereceyi güncelle - NEGATİF DEĞER GÖSTERMEYİ KALDIR
            const displayAngle = Math.abs(newAngle).toFixed(1);
            degree.textContent = `${displayAngle}°`;
        }
    }

    // Sayfanın tam olarak yüklenmesini bekle
    window.addEventListener('load', () => {
        // Biraz gecikme ekle, uygulamanın tam olarak yüklenmesi için
        setTimeout(watchCameraAngle, 2000);
    });
    
    // Google Earth'ün asenkron yüklenme durumları için ek bir kontrol
    if (document.readyState === 'complete') {
        setTimeout(watchCameraAngle, 2000);
    }
})();