您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
多功能转换图寻复盘链接成谷歌链接,显示地点位置信息和拍摄时间,原作者lemures
// ==UserScript== // @name 图寻复盘mode // @namespace https://tuxun.fun/ // @version 4.4 // @description 多功能转换图寻复盘链接成谷歌链接,显示地点位置信息和拍摄时间,原作者lemures // @match https://tuxun.fun/replay?gameId=* // @match https://tuxun.fun/replay-pano?gameId=*&round=* // @icon https://s2.loli.net/2024/05/29/laZyuemTzKt3O5s.png // @author Rylleon // @grant GM_setClipboard // @grant GM_addStyle // @copyright Rylleon // @license All Rights Reserved // ==/UserScript== (function() { 'use strict'; GM_addStyle(` #coordinates-container { position: fixed; top: 100px; left: 10px; padding: 10px; border-radius: 20px !important; z-index: 1000; display: flex; flex-direction: column; width: 160px; } #coordinates-container button { cursor: pointer; width: 100% !important; font-weight: bold !important; border: 8px solid #000000 !important; text-align: left !important; padding-left: 8px !important; padding-right: 8px !important; backdrop-filter: blur(10px); margin-bottom: 5px; border-radius: 4px; background-color: #000000 !important; color: #A0A0A0 !important; }; #conversion-mode { font-family: Arial, sans-serif !important; color: #000000 !important; text-shadow: -1px -1px 0 #A0A0A0, 1px -1px 0 #A0A0A0, -1px 1px 0 #A0A0A0, 1px 1px 0 #A0A0A0 !important; margin-bottom: 5px !important; } .link-button { background: none!important; border: none; padding: 0!important; color: #FFCC00 !important; text-decoration: underline; cursor: pointer; } .link-button:hover { color: #FFCC00 !important; } `); const container = document.createElement('div'); container.id = 'coordinates-container'; document.body.appendChild(container); const conversionModeLabel = document.createElement('div'); conversionModeLabel.id = 'conversion-mode'; conversionModeLabel.textContent = 'Conversion Mode'; container.appendChild(conversionModeLabel); const openButton = document.createElement('button'); openButton.textContent = 'Open in Google Map'; container.appendChild(openButton); const copyButton = document.createElement('button'); copyButton.textContent = 'Copy to Clipboard'; container.appendChild(copyButton); let currentLink = ''; openButton.onclick = () => window.open(currentLink, '_blank'); copyButton.onclick = () => { GM_setClipboard(currentLink, 'text'); alert('Link copied to clipboard'); }; const areaButton = document.createElement('button'); areaButton.textContent = 'Area'; container.appendChild(areaButton); const streetButton = document.createElement('button'); streetButton.textContent = 'Street'; container.appendChild(streetButton); const timeButton = document.createElement('button'); timeButton.textContent = 'Time'; container.appendChild(timeButton); let globalTimeInfo = null; let globalAreaInfo = null; let globalStreetInfo = null; function updateButtonContent() { areaButton.textContent = globalAreaInfo ? `${globalAreaInfo}` : 'Area'; streetButton.textContent = globalStreetInfo ? `${globalStreetInfo}` : 'Street'; timeButton.textContent = globalTimeInfo ? `${globalTimeInfo}` : 'Time'; } setInterval(updateButtonContent, 1000); var realSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(value) { this.addEventListener('load', function() { if (this._url && this._url.includes('https://tuxun.fun/api/v0/tuxun/mapProxy/getGooglePanoInfoPost')) { const responseText = this.responseText; const coordinatePattern = /\[\[null,null,(-?\d+\.\d+),(-?\d+\.\d+)\],\[\d+\.\d+\],\[\d+\.\d+,\d+\.\d+,\d+\.\d+\]\]|\[\s*null,\s*null,\s*(-?\d+\.\d+),\s*(-?\d+\.\d+)\s*\]/; const coordinateMatches = coordinatePattern.exec(responseText); if (coordinateMatches) { const latitude = coordinateMatches[1] || coordinateMatches[3]; const longitude = coordinateMatches[2] || coordinateMatches[4]; if (latitude && longitude) { currentLink = `https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${latitude},${longitude}`; } } const countryPattern = /,\s*"([A-Z]{2})"\s*\],null,\[/; const countryMatches = countryPattern.exec(responseText); let countryCode = countryMatches ? countryMatches[1] : '未知国家'; const areaPattern = /\[\[\s*"([^"]+)",\s*"[a-z]{2}"\s*\],\s*\["([^"]+)",\s*"zh"\s*\]\]/; const areaMatches = areaPattern.exec(responseText); if (areaMatches && areaMatches.length >= 3) { globalAreaInfo = `${countryCode}, ${areaMatches[2]}`; } const fullAddressPattern = /\[\s*null,\s*null,\s*\[\s*\["([^"]+)",\s*"[a-z]{2}"\s*\]\]/; const addressMatches = fullAddressPattern.exec(responseText); if (addressMatches && addressMatches.length > 1) { globalStreetInfo = addressMatches[1]; } else { globalStreetInfo = '未知地址'; } const timePattern = /\[\d+,\d+,\d+,null,null,\[null,null,"launch",\[\d+\]\],null,\[(\d{4}),(\d{1,2})\]\]/; const timeMatches = timePattern.exec(responseText); if (timeMatches) { globalTimeInfo = `${timeMatches[1]}年${timeMatches[2]}月`; } else { globalTimeInfo = '未知时间'; } } }, false); realSend.call(this, value); }; XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { this._url = url; this.realOpen(method, url, async, user, pass); }; //map window.addEventListener('popstate', function(event) { const container = document.getElementById('coordinates-container'); if (container) { container.remove(); } }); })();