petaviron : click save button to download transformed image
Created
September 8, 2020 12:02
-
-
Save frogcat/b4172e63310e15e25681cd84994599b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<title>petaviron</title> | |
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" /> | |
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" /> | |
<script src="https://unpkg.com/jszip@3.1.5/dist/jszip.min.js"></script> | |
<script src="https://unpkg.com/file-saver@1.3.8/FileSaver.min.js"></script> | |
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> | |
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script> | |
<script src="https://unpkg.com/leaflet-hash@0.2.1/leaflet-hash.js"></script> | |
<script src="https://frogcat.github.io/leaflet-imageoverlay-gcp/dist/leaflet-imageoverlay-gcp.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/exif-js"></script> | |
<style> | |
button { | |
cursor: pointer; | |
} | |
#map { | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
} | |
#control { | |
position: absolute; | |
bottom: 10px; | |
left: 10px; | |
width: 140px; | |
height: auto; | |
border-radius: 10px; | |
padding: 10px; | |
background: rgba(0, 0, 0, 0.75); | |
z-index: 1000; | |
} | |
#opacityText { | |
width: 100%; | |
font-size: 10pt; | |
color: white; | |
display: block; | |
margin: 0; | |
padding: 0; | |
text-align: center; | |
font-family: Consolas; | |
font-size: 14pt; | |
} | |
#opacity { | |
width: 100%; | |
display: block; | |
margin: 0; | |
padding: 0; | |
} | |
.instruction { | |
text-align: center; | |
} | |
.gr { | |
font-size: 14pt; | |
font-family: Consolas; | |
} | |
button.gr { | |
background: black; | |
color: white; | |
border-radius: 10px; | |
border: none; | |
padding: 10px; | |
} | |
button.gr:hover { | |
background: orange; | |
} | |
#save { | |
font-family: Consolas; | |
font-size: 14pt; | |
display: block; | |
width: 100%; | |
background: white; | |
color: black; | |
margin: 7px 0; | |
border: none; | |
border-radius: 10px; | |
} | |
#save:hover { | |
background: orange; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<div id="control" style="display:none;"> | |
<label for="opacity" id="opacityText">opacity 75%</label> | |
<input type="range" id="opacity" min="0" max="1" step="0.01" value="0.75" /> | |
<button id="save">save</button> | |
</div> | |
<script src="script.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var map = L.map("map", L.extend({ | |
maxZoom: 20, | |
center: [35.61748, 139.62071], | |
zoom: 14 | |
}, L.Hash.parseHash(location.hash))); | |
map.zoomControl.setPosition("bottomright"); | |
map.attributionControl.setPrefix("<a href='https://github.com/frogcat/petaviron'>petaviron</a>"); | |
L.hash(map); | |
L.control.layers({ | |
"GSI photo": L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg", { | |
attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>", | |
maxNativeZoom: 18, | |
maxZoom: 20 | |
}).addTo(map), | |
"GSI pale": L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png", { | |
attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>", | |
maxNativeZoom: 18, | |
maxZoom: 20 | |
}), | |
"GSI std": L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png", { | |
attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>", | |
maxNativeZoom: 18, | |
maxZoom: 20 | |
}), | |
"OpenStreetMap": L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { | |
attribution: "© <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors", | |
maxNativeZoom: 18, | |
maxZoom: 20 | |
}) | |
}).addTo(map); | |
var popup = L.popup({ | |
closeButton: false, | |
autoClose: false, | |
closeOnEscapeKey: false, | |
closeOnClick: false, | |
className: "instruction" | |
}); | |
popup.setLatLng(map.getCenter()); | |
popup.setContent("<button id='start' class='gr'>Click me to overlay your image</button>"); | |
popup.openOn(map); | |
map.on("moveend", function() { | |
popup.setLatLng(map.getCenter()); | |
}); | |
$("#start").on("click", function() { | |
$("<input type='file' accept='image/*'/>").change(function() { | |
var file = Array.apply(null, this.files).find(function(f) { | |
return f.type.indexOf("image/") === 0; | |
}); | |
if (!file) return; | |
EXIF.getData(file, function() { | |
var data = EXIF.getAllTags(file); | |
if (data["GPSLatitude"] && data["GPSLongitude"]) { | |
var ll = [ | |
data["GPSLatitude"], | |
data["GPSLongitude"] | |
].map(a => a[0] + a[1] / 60 + a[2] / 3600); | |
if (data["GPSLatitudeRef"] !== "N") ll[0] *= -1; | |
if (data["GPSLongitudeRef"] !== "E") ll[1] *= -1; | |
if (confirm("EXIF GPSLatitude/GPSLongitude found.\n [OK] Set the map view to EXIF location \n [Cancel] Don't change the map view")) | |
map.panTo(ll, { | |
animate: false | |
}); | |
} | |
var image = new Image(); | |
image.title = file.name; | |
image.crossOrigin = "anonymous"; | |
image.onload = function() { | |
window.URL.revokeObjectURL(image.src); | |
init(image); | |
}; | |
image.src = window.URL.createObjectURL(file); | |
}); | |
}).click(); | |
}); | |
function init(img) { | |
map.closePopup(); | |
$("#control").fadeIn(); | |
var initialControlPoints = (function() { | |
var size = map.getSize(); | |
var src = L.point(img.naturalWidth, img.naturalHeight); | |
var dst = src.multiplyBy(Math.min(size.x / src.x * 0.8, size.y / src.y * 0.8, 1)); | |
var c = size.divideBy(2); | |
var d = dst.divideBy(2); | |
return [{ | |
imagePoint: L.point(0, 0), | |
latlng: map.containerPointToLatLng(L.point(c.x - d.x, c.y - d.y)) | |
}, { | |
imagePoint: L.point(src.x, 0), | |
latlng: map.containerPointToLatLng(L.point(c.x + d.x, c.y - d.y)) | |
}, { | |
imagePoint: L.point(src.x, src.y), | |
latlng: map.containerPointToLatLng(L.point(c.x + d.x, c.y + d.y)) | |
}, { | |
imagePoint: L.point(0, src.y), | |
latlng: map.containerPointToLatLng(L.point(c.x - d.x, c.y + d.y)) | |
}]; | |
})(); | |
var markerGroup = L.featureGroup([]).addTo(map); | |
var overlay = L.imageOverlay.gcp(img, initialControlPoints, { | |
opacity: $("#opacity").val() | |
}).addTo(map); | |
overlay.on("click", function(e) { | |
var p = overlay.containerPointToImagePoint(e.containerPoint); | |
if (p === null) return; | |
var button = document.createElement("button"); | |
button.setAttribute("class", "gr"); | |
button.appendChild(document.createTextNode("Click to remove")); | |
var me = L.marker(e.latlng, { | |
draggable: true, | |
imagePoint: p | |
}).bindPopup(button).addTo(markerGroup); | |
button.addEventListener("click", function() { | |
markerGroup.removeLayer(me); | |
}); | |
}); | |
markerGroup.on("layeradd layerremove change", function(e) { | |
if (e.type === "layeradd") { | |
e.layer.on("drag", function() { | |
markerGroup.fire("change"); | |
}); | |
} | |
var markers = markerGroup.getLayers(); | |
if (markers.length < 3) return; | |
overlay.setGroundControlPoints(markers.map(marker => { | |
return { | |
latlng: marker.getLatLng(), | |
imagePoint: marker.options.imagePoint | |
}; | |
})); | |
}).addTo(map); | |
map.on("resize zoom viewreset moveend", function() { | |
markerGroup.fire("change"); | |
}); | |
initialControlPoints.forEach(a => { | |
L.marker(a.latlng, { | |
draggable: true, | |
imagePoint: a.imagePoint | |
}).bindPopup("<span class='gr'>drag me</span>").addTo(markerGroup).openPopup(); | |
}); | |
$("#opacity").on("input", function() { | |
overlay.setOpacity($(this).val()); | |
$("#opacityText").text("opacity " + Math.floor(($(this).val() * 100)) + "%"); | |
}).trigger("input"); | |
$("#save").on("click", function() { | |
if (overlay._canvas) { | |
overlay._canvas.toBlob(function(blob) { | |
saveAs(blob, "petaviron" + (new Date().getTime()) + ".png"); | |
}); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment