fotokmz / index.html
ignaciomdr's picture
Add 2 files
bac1411 verified
raw
history blame contribute delete
19.2 kB
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Foto a KML con UTM WGS84 Zona 18S</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.8.0/proj4.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
#videoElement {
transform: scaleX(-1);
}
#canvasElement {
transform: scaleX(-1);
display: none;
}
#canvasWithOverlay {
display: none;
}
.hidden {
display: none;
}
.kml-download {
animation: pulse 2s infinite;
}
.photo-overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 10px;
font-family: Arial, sans-serif;
}
.photo-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 5px;
text-align: center;
}
.photo-coords {
font-size: 14px;
text-align: center;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div class="container mx-auto px-4 py-8">
<div class="max-w-2xl mx-auto bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-8">
<h1 class="text-3xl font-bold text-center text-blue-600 mb-6">
<i class="fas fa-camera-retro mr-2"></i> Foto a KML con UTM WGS84 Zona 18S
</h1>
<div class="mb-6 bg-blue-50 p-4 rounded-lg">
<h2 class="text-xl font-semibold text-blue-800 mb-2">
<i class="fas fa-info-circle mr-2"></i>Instrucciones:
</h2>
<ol class="list-decimal pl-5 space-y-2 text-gray-700">
<li>Permite el acceso a la c谩mara cuando se te solicite.</li>
<li>Enfoca lo que quieras capturar en la vista previa.</li>
<li>Haz clic en "Tomar Foto" para capturar la imagen.</li>
<li>La aplicaci贸n obtendr谩 autom谩ticamente tu ubicaci贸n.</li>
<li>Haz clic en "Generar KML" para descargar el archivo con la foto y coordenadas UTM WGS84 Zona 18S.</li>
</ol>
</div>
<!-- Vista de c谩mara -->
<div id="cameraView" class="mb-6">
<div class="relative bg-black rounded-lg overflow-hidden">
<video id="videoElement" autoplay playsinline class="w-full h-auto"></video>
<canvas id="canvasElement"></canvas>
<canvas id="canvasWithOverlay"></canvas>
<div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4">
<button id="captureBtn" class="w-16 h-16 mx-auto bg-white rounded-full flex items-center justify-center shadow-lg hover:bg-gray-100 transition">
<i class="fas fa-camera text-2xl text-gray-800"></i>
</button>
</div>
</div>
</div>
<!-- Vista de foto capturada -->
<div id="photoView" class="hidden mb-6">
<div class="relative bg-gray-200 rounded-lg overflow-hidden">
<img id="photoResult" src="" alt="Foto capturada" class="w-full h-auto">
<div id="photoOverlay" class="photo-overlay">
<div class="photo-title">Obra Q72 Ampliaci贸n Ruta S-839</div>
<div id="utmCoords" class="photo-coords"></div>
</div>
<div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/70 to-transparent p-4 flex justify-between items-center">
<button id="retakeBtn" class="px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition">
<i class="fas fa-redo mr-2"></i>Volver a tomar
</button>
<div class="text-white">
<i class="fas fa-map-marker-alt mr-2"></i>
<span id="locationInfo">Obteniendo ubicaci贸n...</span>
</div>
</div>
</div>
</div>
<!-- Controles -->
<div class="flex flex-col space-y-4">
<button id="generateKmlBtn" class="hidden kml-download px-6 py-3 bg-green-600 text-white rounded-lg font-semibold hover:bg-green-700 transition flex items-center justify-center">
<i class="fas fa-file-download mr-2"></i> Generar y Descargar KML
</button>
<div id="errorMsg" class="hidden bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded">
<i class="fas fa-exclamation-triangle mr-2"></i>
<span id="errorText"></span>
</div>
</div>
</div>
</div>
</div>
<script>
// Definir proyecciones UTM Zona 18 Sur (EPSG:32718)
proj4.defs("EPSG:4326", "+proj=longlat +datum=WGS84 +no_defs");
proj4.defs("EPSG:32718", "+proj=utm +zone=18 +south +datum=WGS84 +units=m +no_defs");
// Elementos del DOM
const videoElement = document.getElementById('videoElement');
const canvasElement = document.getElementById('canvasElement');
const canvasWithOverlay = document.getElementById('canvasWithOverlay');
const photoResult = document.getElementById('photoResult');
const captureBtn = document.getElementById('captureBtn');
const retakeBtn = document.getElementById('retakeBtn');
const generateKmlBtn = document.getElementById('generateKmlBtn');
const cameraView = document.getElementById('cameraView');
const photoView = document.getElementById('photoView');
const locationInfo = document.getElementById('locationInfo');
const errorMsg = document.getElementById('errorMsg');
const errorText = document.getElementById('errorText');
const photoOverlay = document.getElementById('photoOverlay');
const utmCoords = document.getElementById('utmCoords');
// Variables de estado
let photoDataUrl = '';
let photoWithOverlayDataUrl = '';
let currentLocation = null;
let photoDateTime = '';
// Iniciar c谩mara
async function startCamera() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'environment' },
audio: false
});
videoElement.srcObject = stream;
} catch (err) {
showError('No se pudo acceder a la c谩mara. Aseg煤rate de haber dado los permisos necesarios.');
console.error('Error al acceder a la c谩mara:', err);
}
}
// Funci贸n para convertir grados decimales a UTM Zona 18 Sur (EPSG:32718)
function toUTM(lat, lng) {
try {
// Convertir de WGS84 (EPSG:4326) a UTM Zona 18 Sur (EPSG:32718)
const utmCoords = proj4("EPSG:4326", "EPSG:32718", [lng, lat]);
return {
zone: 18,
hemisphere: 'S',
easting: utmCoords[0].toFixed(2),
northing: utmCoords[1].toFixed(2)
};
} catch (error) {
console.error('Error en conversi贸n UTM:', error);
return {
zone: 18,
hemisphere: 'S',
easting: 'N/A',
northing: 'N/A'
};
}
}
// Capturar foto y agregar overlay
function capturePhoto() {
const context = canvasElement.getContext('2d');
canvasElement.width = videoElement.videoWidth;
canvasElement.height = videoElement.videoHeight;
context.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height);
photoDataUrl = canvasElement.toDataURL('image/jpeg');
photoResult.src = photoDataUrl;
// Obtener fecha y hora actual
const now = new Date();
photoDateTime = now.toISOString();
// Cambiar vistas
cameraView.classList.add('hidden');
photoView.classList.remove('hidden');
// Obtener ubicaci贸n
getLocation();
}
// Crear imagen con overlay de coordenadas
function createImageWithOverlay() {
return new Promise((resolve) => {
const img = new Image();
img.onload = function() {
// Configurar canvas con overlay
canvasWithOverlay.width = img.width;
canvasWithOverlay.height = img.height;
const ctx = canvasWithOverlay.getContext('2d');
// Dibujar la imagen original
ctx.drawImage(img, 0, 0);
// Configurar estilo para el texto
ctx.font = 'bold 24px Arial';
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
// Dibujar fondo semitransparente para el texto
const text = "Obra Q72 Ampliaci贸n Ruta S-839";
const textWidth = ctx.measureText(text).width;
const padding = 20;
const rectHeight = 80;
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillRect(
(canvasWithOverlay.width - textWidth - padding * 2) / 2,
canvasWithOverlay.height - rectHeight - 10,
textWidth + padding * 2,
rectHeight
);
// Dibujar t铆tulo
ctx.fillStyle = 'white';
ctx.font = 'bold 24px Arial';
ctx.fillText(
"Obra Q72 Ampliaci贸n Ruta S-839",
canvasWithOverlay.width / 2,
canvasWithOverlay.height - 50
);
// Dibujar coordenadas UTM Zona 18S
if (currentLocation) {
const utm = toUTM(currentLocation.lat, currentLocation.lng);
const coordsText = `UTM WGS84 Zona ${utm.zone}${utm.hemisphere} Este: ${utm.easting} Norte: ${utm.northing}`;
ctx.font = '18px Arial';
ctx.fillText(
coordsText,
canvasWithOverlay.width / 2,
canvasWithOverlay.height - 20
);
}
// Obtener la imagen con overlay como Data URL
photoWithOverlayDataUrl = canvasWithOverlay.toDataURL('image/jpeg');
resolve(photoWithOverlayDataUrl);
};
img.src = photoDataUrl;
});
}
// Obtener ubicaci贸n
function getLocation() {
if (navigator.geolocation) {
locationInfo.textContent = 'Obteniendo ubicaci贸n...';
navigator.geolocation.getCurrentPosition(
async (position) => {
currentLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude,
alt: position.coords.altitude || 0
};
// Convertir a UTM Zona 18S usando proj4js
const utm = toUTM(currentLocation.lat, currentLocation.lng);
// Mostrar en el overlay
locationInfo.textContent = `UTM WGS84 Zona ${utm.zone}${utm.hemisphere}`;
utmCoords.textContent = `Este: ${utm.easting} Norte: ${utm.northing}`;
// Crear imagen con overlay
await createImageWithOverlay();
// Mostrar bot贸n de generar KML
generateKmlBtn.classList.remove('hidden');
},
(error) => {
let errorMessage = 'No se pudo obtener la ubicaci贸n.';
switch(error.code) {
case error.PERMISSION_DENIED:
errorMessage = 'Permiso de ubicaci贸n denegado.';
break;
case error.POSITION_UNAVAILABLE:
errorMessage = 'Informaci贸n de ubicaci贸n no disponible.';
break;
case error.TIMEOUT:
errorMessage = 'Tiempo de espera para obtener ubicaci贸n agotado.';
break;
}
locationInfo.textContent = errorMessage;
showError(errorMessage);
},
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 }
);
} else {
showError('Geolocalizaci贸n no es soportada por tu navegador.');
}
}
// Volver a tomar foto
function retakePhoto() {
cameraView.classList.remove('hidden');
photoView.classList.add('hidden');
generateKmlBtn.classList.add('hidden');
currentLocation = null;
photoDataUrl = '';
photoWithOverlayDataUrl = '';
startCamera();
}
// Generar y descargar KML con UTM WGS84 Zona 18S
async function generateKml() {
if (!currentLocation || !photoDataUrl) {
showError('No hay foto o ubicaci贸n disponible.');
return;
}
// Asegurarse de que tenemos la imagen con overlay
if (!photoWithOverlayDataUrl) {
await createImageWithOverlay();
}
// Convertir a UTM Zona 18S usando proj4js
const utm = toUTM(currentLocation.lat, currentLocation.lng);
// Crear contenido KML
const kmlContent = `<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Obra Q72 Ampliaci贸n Ruta S-839</name>
<description><![CDATA[
<h1>OBRA Q72 AMPLIACI脫N RUTA S-839</h1>
<img src="${photoWithOverlayDataUrl}" width="800" style="display: block; margin: 0 auto;"/>
<h2>Informaci贸n de la obra</h2>
<p><strong>Fecha:</strong> ${new Date(photoDateTime).toLocaleString()}</p>
<p><strong>Coordenadas UTM WGS84 Zona 18S</strong></p>
<p><strong>Este:</strong> ${utm.easting}</p>
<p><strong>Norte:</strong> ${utm.northing}</p>
<p><strong>Altitud:</strong> ${currentLocation.alt.toFixed(2)} metros</p>
<p><strong>Coordenadas originales WGS84:</strong> ${currentLocation.lat.toFixed(6)}, ${currentLocation.lng.toFixed(6)}</p>
]]></description>
<Placemark>
<name>Ubicaci贸n exacta UTM WGS84 Zona 18S</name>
<description><![CDATA[
<p><strong>Este:</strong> ${utm.easting}</p>
<p><strong>Norte:</strong> ${utm.northing}</p>
<p><strong>Zona:</strong> ${utm.zone}${utm.hemisphere}</p>
]]></description>
<Point>
<coordinates>${currentLocation.lng},${currentLocation.lat},${currentLocation.alt}</coordinates>
</Point>
<Style>
<IconStyle>
<Icon>
<href>https://maps.google.com/mapfiles/kml/shapes/placemark_circle.png</href>
</Icon>
<color>ff0000ff</color>
<scale>1.2</scale>
</IconStyle>
</Style>
</Placemark>
</Document>
</kml>`;
// Crear y descargar archivo
const blob = new Blob([kmlContent], { type: 'application/vnd.google-earth.kml+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `Obra_Q72_UTM18S_${new Date(photoDateTime).toISOString().replace(/[:.]/g, '-')}.kml`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Mostrar error
function showError(message) {
errorText.textContent = message;
errorMsg.classList.remove('hidden');
setTimeout(() => errorMsg.classList.add('hidden'), 5000);
}
// Event listeners
captureBtn.addEventListener('click', capturePhoto);
retakeBtn.addEventListener('click', retakePhoto);
generateKmlBtn.addEventListener('click', generateKml);
// Iniciar la aplicaci贸n
startCamera();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 馃К <a href="https://enzostvs-deepsite.hf.space?remix=ignaciomdr/fotokmz" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>