Street View Snapper

Download location and orientation in Google Street View to a local file.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

Advertisement:

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

Advertisement:

// ==UserScript==
// @name         Street View Snapper
// @name:ja         Street View スナップ
// @namespace    http://tampermonkey.net/
// @version      0.1.1.7
// @description  Download location and orientation in Google Street View to a local file.
// @description:ja  Google Street View 内の位置と方向情報を geoJSON 及び KML 形式でダウンロードします。
// @author       Paul Richter
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=google.com
// @grant        none
// @license      GPL-3.0-or-later
// ==/UserScript==

function is_google_gsv() {
    return location.href.includes("google.com/maps") && location.href.includes('@') && location.href.includes('data=')
}

function is_embedded_gm() {
    return document.querySelector(".gm-iv-address-link") && document.querySelector(".gm-iv-short-address-description")
}

function wrap_xml(name, value) {
    if(name == 'url') {
        value = value.replace('&', '&') ;
    }
    return `<Data name="${name}"><value>${value}</value></Data>`
}

function as_kml(data) {
    let kml_str = "<kml xmlns=\"http://www.opengis.net/kml/2.2\"><Document>\n<Placemark>\n" ;

    const coords = data.geometry.coordinates ;
    const coord_str = `<coordinates>${coords[0]}, ${coords[1]}</coordinates>`

    kml_str += "<Point>" + coord_str + "</Point>"

    kml_str += "<ExtendedData>\n" ;

    Object.entries(data.properties).forEach(([k, v])=> {
        kml_str += wrap_xml(k, v) ;
    }) ;

    kml_str += "</ExtendedData>\n"

    kml_str += "</Placemark>\n</Document>\n</kml>" ;

    return kml_str ;
}

function gsv_long_address() {
    const attribDiv = document.querySelector('[data-attribution-url="//www.google.com/streetview"]') ;

    if(attribDiv) {
        return attribDiv.parentElement.parentElement.parentElement.parentElement.children[1].firstChild.innerText ;
    }
    return null ;
}



function crack_locstr(locstr) {
    const loc_fields = locstr.split(',') ;

    let data = {
        lng:null,
        lat:null,
        height:null,
        zoom:null,
        heading:null,
        tilt:null
    } ;

    loc_fields.forEach((field) => {
        if(field[0] == '@') {
            data.lat = parseFloat(field.slice(1)) ;
            return ;
        }
        const lastChar = field.slice(-1) ;

        if('ahty'.includes(lastChar)) {
            const val = parseFloat(field.slice(0, -1)) ;
            switch(lastChar) {
                case 'a':
                    data.height = val;
                    break;
                case 'h':
                    data.heading = val;
                    break;
                case 't':
                    data.tilt = val;
                    break;
                case 'y':
                    data.zoom = val;
                    break;
                default:
            }
        } else {
            data.lng = parseFloat(field) ;
        }
    }) ;
    return data ;
}

function snap_gsv(label, format) {
    let url = location.href;
    let place = "";

    console.log("Format", format) ;

    if (is_google_gsv()) {
        console.log("This is google maps in street view mode.") ;
        const title_fields = document.title.split(' - ');
        place = title_fields[0] ;

        const place_sub = gsv_long_address() ;
        if (place_sub) {
            place += " - " + place_sub
        }
    } else if (is_embedded_gm()) {
        console.log("This is a site with an embedded google map in street view mode.") ;

        const addressLink = document.querySelector(".gm-iv-address-link") ;
        const anchor = addressLink.getElementsByTagName('a')[0] ;
        url = anchor.getAttribute("href") ;

        place = document.querySelector(".gm-iv-short-address-description").innerText ;
        const place_long = document.querySelector(".gm-iv-long-address-description").innerText ;

        if(place_long.length > 0) {
            place += " - " + place_long ;
        }
        //also check for "gm-iv-profile-url") ;
    } else {
        alert("You are not viewing a Google Street View page") ;
        return ;
    }

    const url_fields = url.split('/');
    const locstr = url_fields.at(-2) ;// '/@'
    const svdata = url_fields.at(-1) ;// '/data='

    const loc_fields = crack_locstr(locstr) ;

    const data={
        type:"Feature",
        geometry: {
            type:"Point",
            coordinates:[loc_fields.lng, loc_fields.lat],
        },
        properties: {
            heading:loc_fields.heading,
            tilt:loc_fields.tilt,
            zoom:loc_fields.zoom,
            label:label,
            place: place,
            url:url
        }
    };

    let dataStr = JSON.stringify(data,null,2) ;
    let extension = ".geojson" ;

    if(format == "kml") {
        dataStr = as_kml(data) ;
        extension = ".kml"
    }

    const blob=new Blob([dataStr],{type:"application/json"});
    const a=document.createElement("a");

    a.href=URL.createObjectURL(blob);
    a.download=`gsvs_${place}_${label}_${Date.now()}${extension}`;
    a.click();
    setTimeout(()=>URL.revokeObjectURL(a.href),1000);
}

window.snap_gsv = snap_gsv ;