Street View Snapper

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

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 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 ;