您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
농지공간포털의 지도를 다운로드 하는 스크립트입니다. 빨간색 버튼을 클릭하면 다운로드가 시작됩니다.
// ==UserScript== // @name 농지공간포털 지도 다운로더 // @version 0.3 // @description 농지공간포털의 지도를 다운로드 하는 스크립트입니다. 빨간색 버튼을 클릭하면 다운로드가 시작됩니다. // @author refracta // @match https://njy.mafra.go.kr/map/mapMain.do // @icon https://www.google.com/s2/favicons?sz=64&domain=go.kr // @grant none // @license MIT // @namespace https://greasyfork.org/users/467840 // ==/UserScript== (async function () { function waitFor(checkFunction, checkDelay = 100) { return new Promise(resolve => { let i = setInterval(_ => { try { let check = checkFunction(); check ? clearInterval(i) || resolve(check) : void 0 } catch (e) { } }, checkDelay); }); } let map = await waitFor(_ => git.map); function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } function hashImageData(imageData) { return imageData.data.reduce((hash, byte) => hash + byte, 0); } function waitCanvas(samplingTime = 250, n = 4) { let canvas = document.querySelector('canvas'); return new Promise(async (resolve, reject) => { const context = canvas.getContext('2d'); let queue = [hashImageData(context.getImageData(0, 0, canvas.width, canvas.height))]; let currentHash; do { await sleep(samplingTime); currentHash = hashImageData(context.getImageData(0, 0, canvas.width, canvas.height)); queue.push(currentHash); queue = queue.slice(-n); } while (!(queue.length === n && queue.reduce((a, c) => a && currentHash === c, true))) resolve(); }); } function getOutline() { let canvas = document.querySelector('canvas'); let ctx = canvas.getContext('2d'); let image = ctx.getImageData(0, 0, canvas.width, canvas.height); let pixels = image.data; let width = image.width; let height = image.height; let up = []; let down = []; let left = []; let right = []; for (let x = 0; x < width; x++) { up.push(pixels.slice(x * 4, x * 4 + 4)); down.push(pixels.slice((width * (height - 1) + x) * 4, (width * (height - 1) + x) * 4 + 4)); } for (let y = 0; y < height; y++) { left.push(pixels.slice(y * width * 4, y * width * 4 + 4)); right.push(pixels.slice((y * width + (width - 1)) * 4, (y * width + (width - 1)) * 4 + 4)); } return {up, down, left, right}; } function setAirMode(visible) { git.layer.getLayerById('AIR_21', map).setVisible(visible); } function arePixelArraysEqual(arr1, arr2, targetRate = 0.0009) { if (arr1.length !== arr2.length) { return false; } let count = 0; for (let i = 0; i < arr1.length; i++) { for (let j = 0; j < 4; j++) { if (arr1[i][j] !== arr2[i][j]) { count++; } } } let missRate = count / (arr1.length * 4); console.log(`missRate: ${missRate * 100}%`); return missRate <= targetRate; } function saveCanvas(name = 'canvas-image.png') { console.log(`saveCanvas(${name})`); let canvas = document.querySelector("canvas"); let dataURL = canvas.toDataURL("image/png"); let link = document.createElement("a"); link.href = dataURL; link.download = name; document.body.appendChild(link); link.click(); document.body.removeChild(link); } function createElement(str) { let div = document.createElement('div'); div.innerHTML = str; let container = document.createDocumentFragment(); for (let i = 0; i < div.childNodes.length; i++) { let node = div.childNodes[i].cloneNode(true); container.appendChild(node); } return container.childNodes[0]; } document.querySelector('.mapControl_list').append(createElement(`<li> <div id="autoDownload" class="item"> <a href="#" title="다운로드" class="btn btn_map_control15" style="background-color: red"> <span>다운로드</span> </a> </div> </li>`)); function updateText(text) { let pinpoint = document.querySelector('.location_wrap > .pinpoint'); let notificationBar = document.querySelector('#notification-bar'); if (!notificationBar) { let span = document.createElement('span'); span.id = 'notification-bar'; pinpoint.append(span); notificationBar = span; } notificationBar.textContent = ' ※ ' + text; } async function run(saveData) { await waitCanvas(); let view = map.getView(); let size = map.getSize(); size = size.map(Math.floor); let resolution = view.getResolution(); let screenMeters = size.map(s => s * resolution); let startCenter = window.startCenter || view.getCenter(); let zoomLevel = window.zoomLevel || view.getZoom(); view.setZoom(zoomLevel); view.setCenter(startCenter); await waitCanvas(); let range2D = window.range2D || [1000, 200]; range2D[1] = -range2D[1]; let airMode = window.airMode !== undefined ? window.airMode : true; let endCenter = startCenter.map((e, i) => e + range2D[i]); async function move(x, y) { view.setCenter([x, y]); await waitCanvas(); } async function moveRelative(xDelta, yDelta) { let center = view.getCenter(); await move(center[0] + xDelta, center[1] + yDelta); } const deltaMap = {}; async function movePrecisely(direction, previousOutline) { console.log(`movePrecisely(${direction})`); let originalCenter = view.getCenter(); if (direction === 'up') { await moveRelative(0, screenMeters[1] + resolution); } else if (direction === 'down') { await moveRelative(0, -screenMeters[1] - resolution); } else if (direction === 'left') { await moveRelative(-screenMeters[0] - resolution, 0); } else if (direction === 'right') { await moveRelative(screenMeters[0] + resolution, 0); } let center = view.getCenter(); let counter = 1; let deltas = Object.keys(deltaMap).sort((a, b) => deltaMap[b] - deltaMap[a]); while (true) { let delta; if (deltas.length > 0) { delta = deltas.shift(); } else { delta = counter; while (deltaMap[delta]) { delta++; } counter = delta + 1; } if (delta > 10) { localStorage.forceRun = true; location.reload(); } console.log(`center=${view.getCenter()} direction=${direction}, delta=${delta}, deltaMap=${JSON.stringify(deltaMap)}`); if (direction === 'up') { await move(center[0], center[1] - resolution * delta); } else if (direction === 'down') { await move(center[0], center[1] + resolution * delta); } else if (direction === 'left') { await move(center[0] + resolution * delta, center[1]); } else if (direction === 'right') { await move(center[0] - resolution * delta, center[1]); } let pixelCheck; if (direction === 'up') { pixelCheck = arePixelArraysEqual(previousOutline.up, getOutline().down); } else if (direction === 'down') { pixelCheck = arePixelArraysEqual(previousOutline.down, getOutline().up); } else if (direction === 'left') { pixelCheck = arePixelArraysEqual(previousOutline.left, getOutline().right); } else if (direction === 'right') { pixelCheck = arePixelArraysEqual(previousOutline.right, getOutline().left); } if (pixelCheck) { if (direction === 'up') { await moveRelative(0, resolution); } else if (direction === 'down') { await moveRelative(0, -resolution); } else if (direction === 'left') { await moveRelative(-resolution, 0); } else if (direction === 'right') { await moveRelative(resolution, 0); } deltaMap[delta] = deltaMap[delta] === undefined ? 1 : deltaMap[delta] + 1; return; } } } if (Object.keys(saveData).length !== 0) { console.log('Continue from saveData'); startCenter = saveData.startCenter; range2D = saveData.range2D; airMode = saveData.airMode; endCenter = saveData.endCenter; zoomLevel = saveData.zoomLevel; } console.log(`size: ${size}`); console.log(`resolution: ${resolution}`); console.log(`screenMeters: ${screenMeters}`); console.log(`startCenter: ${startCenter}`); console.log(`endCenter: ${endCenter}`); let outline = getOutline(); let newCenter = saveData.newCenter || startCenter; for (let y = saveData.y || startCenter[1], yCount = saveData.yCount || 0; y > endCenter[1]; y = newCenter[1], yCount++) { let yCenter = saveData.yCenter || newCenter; for (let x = saveData.x || startCenter[0], xCount = saveData.xCount || 0; x < endCenter[0]; x = newCenter[0], xCount++) { if (Object.keys(saveData).length !== 0) { saveData = {}; } updateText(`CurrentProcess: ${Math.floor(x - startCenter[0])}/${Math.floor(endCenter[0] - startCenter[0])}, ${Math.floor(startCenter[1] - y)}/${Math.floor(startCenter[1] - endCenter[1])}`) console.log(`lastCenter: ${view.getCenter()}`); let currentCenter = view.getCenter(); if (!(x === currentCenter[0] && y === currentCenter[1])) { view.setZoom(zoomLevel); view.setCenter([x, y]); await waitCanvas(); outline = getOutline(); } // Core logic if (airMode) { setAirMode(true); await waitCanvas(); } saveCanvas(`${xCount}x${yCount}.png`); if (airMode) { setAirMode(false); await waitCanvas(); } if (window.currentSaveData) { localStorage.isRunning = true; localStorage.saveData = JSON.stringify(window.currentSaveData); } window.currentSaveData = { x: x, y: y, xCount: xCount, yCount: yCount, newCenter, startCenter, range2D, airMode, endCenter, yCenter, zoomLevel: view.getZoom() }; // Next X await movePrecisely('right', outline); newCenter = view.getCenter(); outline = getOutline(); } // Next Y await move(yCenter[0], yCenter[1]); await movePrecisely('down', getOutline()); newCenter = view.getCenter(); outline = getOutline(); } localStorage.isRunning = false; localStorage.forceRun = false; } let c1, c2; map.on('singleclick', function (e) { c1 = e.coordinate; console.log(`startCenter: ${c1}, endCenter: ${c2}`); if (c1 && c2) { console.log(`range2D: ${c1.map((e, i) => Math.abs(e - c2[i]))}`); } }); map.getViewport().addEventListener('contextmenu', function (e) { e.preventDefault(); c2 = map.getEventCoordinate(e); console.log(`startCenter: ${c1}, endCenter: ${c2}`); if (c1 && c2) { console.log(`range2D: ${c1.map((e, i) => Math.abs(e - c2[i]))}`); } }); if (localStorage.isRunning === 'true') { if (localStorage.forceRun === 'true' || confirm('Continue?')) { localStorage.forceRun = false; await run(JSON.parse(localStorage.saveData)); } else { localStorage.isRunning = false; localStorage.forceRun = false; } } document.querySelector('#autoDownload').addEventListener('click', _ => run({})); // window.zoomLevel = 11; // window.startCenter = [185386.5028661047, 395956.31206765346]; // window.range2D = [28285.49491734401, 31374.144608640752]; })();