Google Maps Coordinates Grabber

Once in Google Maps, click on the map (Do not click on markers) a popup should show at the bottom with the place and the coordinates displayed in the last line. If everything works as expected you should see a line of text on top of the map with the confirmation of the coordinates been copied to clipboard. Press Control + Shift + L while on streetview to get the coordinates from the URL. (Doesn't work on Firefox)

< 腳本Google Maps Coordinates Grabber的回應

評論:正評 - 腳本一切正常

§
發表於:2025-10-02

I have used Gemini to modify the script to be able to copy from places with names/labels with copy button.
// ==UserScript==
// @name Google Maps Coordinates Grabber
// @version 0.5.3
// @description Adds a professional "Copy Coords" icon button to the sidebar for named places and allows copying coordinates from pins and Street View.
// @author MrMike (modified by Gemini)
// @namespace https://greasyfork.org/en/users/250979-mrmike
// @include https://*google*/maps/*
// @grant none
// @run-at document-end
// @noframes
// @downloadURL https://update.greasyfork.org/scripts/378597/Google%20Maps%20Coordinates%20Grabber.user.js
// @updateURL https://update.greasyfork.org/scripts/378597/Google%20Maps%20Coordinates%20Grabber.meta.js
// ==/UserScript==

// Leave empty to get just the values separated by a comma
// {{lat}} will be replaced with the latitude value and {{lng}} with the longitude value
const FORMAT = ``;

let theCopiedCoords;

// UPDATED: Replaced the clipboard icon with a map pin icon.
const PIN_ICON_SVG = `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWFwLXBpbiI+PHBhdGggZD0iTTIxIDEwYzAgNy05IDEzLTkgMTNzLTktNi05LTEzYTkgOSAwIDAgMSAxOCAweiI+PC9wYXRoPjxjaXJjbGUgY3g9IjEyIiBjeT0iMTAiIHI9IjMiPjwvY2lyY2xlPjwvc3ZnPg==`;

// Hotkey to grab coordinates from the URL (especially useful in Street View)
document.addEventListener("keypress", (event) => {
if (event.code == "KeyL" && event.ctrlKey && event.shiftKey && !event.altKey && !event.repeat) {
copyCoordinates();
}
});

// This function looks for the "reveal-card" that appears when you click a random spot.
// If it finds it, it copies the coordinates automatically.
setInterval(() => {
const theCard = document.getElementById("reveal-card");
if (theCard) {
const theDialog = theCard.querySelector("div[role='dialog']");
if (theDialog) {
const theCoords = theDialog.lastElementChild.innerText;
const theLatLng = theCoords.replace(/\s/g, "").split(",");

if (theLatLng.length === 2 && theCopiedCoords !== theCoords) {
const theLat = theLatLng[0];
const theLng = theLatLng[1];
if (!isNaN(theLat) && !isNaN(theLng)) {
theCopiedCoords = theCoords; // Set this early to prevent re-copying
copyCoordinatesFromValues(theLat, theLng);
}
}
}
}
}, 1000);

// NEW FUNCTION: Adds the stylish "Copy Coords" button to the main sidebar panel for named places.
function addCopyToPlacePanel() {
// Find the button bar (which contains Directions, Save, etc.) as our anchor point.
const buttonRow = document.querySelector('button[data-value="Directions"]')?.parentElement;

// If the button row exists and our button isn't already there, let's create it.
if (buttonRow && !document.getElementById('gm-copy-coords-btn')) {
const templateButton = buttonRow.querySelector('button');
if (!templateButton) return; // Exit if we can't find a button to copy the style from

// 1. Create the main button element
const copyButton = document.createElement('button');
copyButton.id = 'gm-copy-coords-btn';
copyButton.className = templateButton.className; // Copy all classes to match style
copyButton.setAttribute('aria-label', 'Copy Coordinates');
copyButton.style.flexDirection = 'column'; // Ensure icon and text are stacked

// 2. Create the circular background for the icon
const divBg = document.createElement('div');
// Use the class from the first child of the template button (the background div)
divBg.className = templateButton.children[0].className;

// 3. Create the icon itself
const icon = document.createElement('img');
// Use the class from the icon inside the template button
icon.className = templateButton.children[0].children[0].className;
icon.src = PIN_ICON_SVG;
icon.alt = 'Copy';

// 4. Create the text label below the icon
const label = document.createElement('div');
// Use the class from the text label of the template button
label.className = templateButton.children[1].className;
label.textContent = 'Copy Coords';

// 5. Assemble the button
divBg.appendChild(icon);
copyButton.appendChild(divBg);
copyButton.appendChild(label);

// 6. Add the click functionality
copyButton.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
copyCoordinates(); // This reuses the reliable URL-grabbing function
});

// 7. Insert our new button into the button row, right after "Directions"
const directionsButton = buttonRow.querySelector('button[data-value="Directions"]');
if (directionsButton && directionsButton.nextSibling) {
directionsButton.parentElement.insertBefore(copyButton, directionsButton.nextSibling);
} else {
buttonRow.appendChild(copyButton); // Fallback if it can't be inserted
}
}
// If the button row is gone (panel closed), remove our button to keep things clean.
else if (!buttonRow && document.getElementById('gm-copy-coords-btn')) {
document.getElementById('gm-copy-coords-btn').remove();
}
}

// Check for the place panel every second to add/remove our button.
setInterval(addCopyToPlacePanel, 1000);

// Grabs coordinates from the current URL. Works for everything.
function copyCoordinates() {
const theLink = location.href;
const atSymbolIndex = theLink.indexOf("@");
if (atSymbolIndex === -1) return; // No coordinates in URL

const values = theLink.substring(atSymbolIndex + 1).split(",");
if (values.length >= 2) {
copyCoordinatesFromValues(values[0], values[1]);
}
}

// Central function to format and copy the coordinates.
function copyCoordinatesFromValues(lat, lng) {
let textToCopy;
if (FORMAT) {
textToCopy = FORMAT.replace("{{lat}}", lat).replace("{{lng}}", lng);
} else {
textToCopy = `${lat},${lng}`;
}
copyTextToClipboard(textToCopy);
}

// Displays the "Copied" banner at the top of the screen.
function doDisplay(theData) {
// Remove any existing banner first
const existingBanner = document.getElementById('gm-copy-banner');
if(existingBanner) existingBanner.remove();

const banner = document.createElement("div");
banner.id = 'gm-copy-banner';
banner.innerHTML = `Copied: ${theData}`;
banner.style.cssText = `
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
background-color: #202124;
color: #FFFFFF;
padding: 10px 20px;
border-radius: 8px;
z-index: 99999;
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
text-align: center;
`;
document.body.appendChild(banner);

setTimeout(() => {
banner.remove();
}, 3000);
}

// Universal copy-to-clipboard function.
function copyTextToClipboard(text) {
if (!navigator.clipboard) {
// Fallback for older browsers
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand("copy");
doDisplay(text);
} catch (err) {
console.error('Fallback: Oops, unable to copy', err);
}
document.body.removeChild(textArea);
return;
}
navigator.clipboard.writeText(text).then(() => {
doDisplay(text);
}).catch(err => {
console.error('Async: Could not copy text: ', err);
});
}

發表回覆

登入以回覆