En esta lección se muestra como aceder directamente a algunas funciones del dispositivo.
| 1 | <!DOCTYPE html> |
| 2 | <html lang="es"> |
| 3 | |
| 4 | <head> |
| 5 | |
| 6 | <meta charset="UTF-8"> |
| 7 | <meta name="viewport" |
| 8 | content="width=device-width"> |
| 9 | |
| 10 | <title>GPS</title> |
| 11 | |
| 12 | <style> |
| 13 | html { |
| 14 | color-scheme: light dark; |
| 15 | } |
| 16 | </style> |
| 17 | |
| 18 | </head> |
| 19 | |
| 20 | <body> |
| 21 | |
| 22 | <h1>GPS</h1> |
| 23 | |
| 24 | <p> |
| 25 | <label> |
| 26 | Latitud |
| 27 | <output id="latitud"></output> |
| 28 | </label> |
| 29 | </p> |
| 30 | |
| 31 | <p> |
| 32 | <label> |
| 33 | Longitud |
| 34 | <output id="longitud"></output> |
| 35 | </label> |
| 36 | </p> |
| 37 | |
| 38 | <script> |
| 39 | |
| 40 | navigator.geolocation. |
| 41 | watchPosition(p => { |
| 42 | |
| 43 | latitud.value = |
| 44 | p.coords.latitude |
| 45 | |
| 46 | longitud.value = |
| 47 | p.coords.longitude |
| 48 | |
| 49 | }); |
| 50 | |
| 51 | </script> |
| 52 | |
| 53 | </body> |
| 54 | |
| 55 | </html> |
| 1 | <!DOCTYPE html> |
| 2 | <html lang="es"> |
| 3 | |
| 4 | <head> |
| 5 | |
| 6 | <meta charset="UTF-8"> |
| 7 | <meta name="viewport" |
| 8 | content="width=device-width"> |
| 9 | |
| 10 | <title>Archivos y Cámara</title> |
| 11 | |
| 12 | <style> |
| 13 | html { |
| 14 | color-scheme: light dark; |
| 15 | } |
| 16 | </style> |
| 17 | |
| 18 | </head> |
| 19 | |
| 20 | <body> |
| 21 | |
| 22 | <h1>Archivos y Cámara</h1> |
| 23 | |
| 24 | <p> |
| 25 | <label> |
| 26 | Foto de Móvil |
| 27 | <input type="file" |
| 28 | accept="image/*" |
| 29 | capture="camera"> |
| 30 | </label> |
| 31 | </p> |
| 32 | |
| 33 | <p> |
| 34 | <label> |
| 35 | Video de Móvil |
| 36 | <input type="file" |
| 37 | accept="video/*" |
| 38 | capture=""> |
| 39 | </label> |
| 40 | </p> |
| 41 | |
| 42 | <p> |
| 43 | <label> |
| 44 | Archivo |
| 45 | <input type="file"> |
| 46 | </label> |
| 47 | </p> |
| 48 | |
| 49 | </body> |
| 50 | |
| 51 | </html> |
| 1 | <!DOCTYPE html> |
| 2 | <html> |
| 3 | |
| 4 | <head> |
| 5 | |
| 6 | <meta charset="utf-8"> |
| 7 | <meta name="viewport" |
| 8 | content="width=device-width"> |
| 9 | |
| 10 | <title>Cámara</title> |
| 11 | |
| 12 | <style> |
| 13 | html { |
| 14 | color-scheme: light dark; |
| 15 | } |
| 16 | </style> |
| 17 | |
| 18 | </head> |
| 19 | |
| 20 | <body> |
| 21 | |
| 22 | <h1>Cámara</h1> |
| 23 | |
| 24 | <p> |
| 25 | Para grabar o capturar imagen, |
| 26 | cliquea |
| 27 | <strong>Inicia</strong>. |
| 28 | </p> |
| 29 | |
| 30 | <p> |
| 31 | Para grabar por 5 segundos |
| 32 | cliquea |
| 33 | <strong>Graba</strong> |
| 34 | y cliquea |
| 35 | <strong>Para</strong> para |
| 36 | detener. |
| 37 | </p> |
| 38 | |
| 39 | <p> |
| 40 | Para capturar una imagen de la |
| 41 | cámara, cliquea |
| 42 | <strong>Captura</strong>. |
| 43 | </p> |
| 44 | |
| 45 | <menu style="display: flex; |
| 46 | flex-wrap: wrap; |
| 47 | list-style: none;"> |
| 48 | <li> |
| 49 | <button type="button" |
| 50 | onclick="inicia()"> |
| 51 | Inicia |
| 52 | </button> |
| 53 | </li> |
| 54 | <li> |
| 55 | <button type="button" |
| 56 | onclick="graba()"> |
| 57 | Graba |
| 58 | </button> |
| 59 | </li> |
| 60 | <li> |
| 61 | <button type="button" |
| 62 | onclick="para();"> |
| 63 | Para |
| 64 | </button> |
| 65 | </li> |
| 66 | <li> |
| 67 | <button type="button" |
| 68 | onclick="captura()"> |
| 69 | Captura |
| 70 | </button> |
| 71 | </li> |
| 72 | </menu> |
| 73 | |
| 74 | <section |
| 75 | style="display: inline-block; |
| 76 | vertical-align: top;"> |
| 77 | |
| 78 | <h1>Preview</h1> |
| 79 | |
| 80 | <video id="preview" width="160" |
| 81 | height="120" autoplay |
| 82 | muted></video> |
| 83 | |
| 84 | </section> |
| 85 | |
| 86 | <section |
| 87 | style="display: inline-block; |
| 88 | vertical-align: top;"> |
| 89 | |
| 90 | <h1>Recording</h1> |
| 91 | |
| 92 | <video id="recording" width="160" |
| 93 | height="120" controls></video> |
| 94 | |
| 95 | <p> |
| 96 | <a id="descarga">Descarga</a> |
| 97 | </p> |
| 98 | |
| 99 | <div id="mensajes"></div> |
| 100 | |
| 101 | </section> |
| 102 | |
| 103 | <section |
| 104 | style="display: inline-block; |
| 105 | vertical-align: top;"> |
| 106 | |
| 107 | <h1>Imagen</h1> |
| 108 | |
| 109 | <canvas id="canvas" width="160" |
| 110 | height="120"></canvas> |
| 111 | |
| 112 | <p> |
| 113 | <a id="descargaImagen"> |
| 114 | Descarga</a> |
| 115 | </p> |
| 116 | |
| 117 | </section> |
| 118 | |
| 119 | <script> |
| 120 | |
| 121 | let stream = null |
| 122 | |
| 123 | let TIEMPO_DE_GRABACION = 5000 |
| 124 | |
| 125 | var context = |
| 126 | canvas.getContext('2d') |
| 127 | |
| 128 | async function inicia() { |
| 129 | try { |
| 130 | stream = await navigator |
| 131 | .mediaDevices.getUserMedia({ |
| 132 | video: true, |
| 133 | audio: true |
| 134 | }) |
| 135 | preview.srcObject = stream |
| 136 | descarga.href = stream |
| 137 | preview.captureStream = |
| 138 | preview.captureStream |
| 139 | || preview.mozCaptureStream |
| 140 | await new Promise( |
| 141 | resolve => |
| 142 | preview.onplaying = resolve) |
| 143 | } catch (e) { |
| 144 | log(e.message) |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | async function graba() { |
| 149 | try { |
| 150 | const recordedChunks = |
| 151 | await grabaClip(stream, |
| 152 | TIEMPO_DE_GRABACION) |
| 153 | let recordedBlob = new Blob( |
| 154 | recordedChunks, |
| 155 | { type: "video/webm" }) |
| 156 | recording.src = |
| 157 | URL.createObjectURL( |
| 158 | recordedBlob) |
| 159 | descarga.href = recording.src |
| 160 | descarga.download = |
| 161 | "RecordedVideo.webm" |
| 162 | |
| 163 | log("Exitosamente grabados " |
| 164 | + recordedBlob.size |
| 165 | + " bytes de " |
| 166 | + recordedBlob.type |
| 167 | + " media.") |
| 168 | } catch (e) { |
| 169 | log(e.message) |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | function para() { |
| 174 | detiene(preview.srcObject) |
| 175 | } |
| 176 | |
| 177 | function captura() { |
| 178 | context.drawImage(preview, |
| 179 | 0, 0, 160, 120) |
| 180 | descargaImagen.href = |
| 181 | canvas.toDataURL('image/jpeg') |
| 182 | descargaImagen.download = |
| 183 | "imagen.jpg" |
| 184 | } |
| 185 | |
| 186 | function grabaClip(stream, |
| 187 | milisegundos) { |
| 188 | let recorder = |
| 189 | new MediaRecorder(stream) |
| 190 | let data = [] |
| 191 | recorder.ondataavailable = |
| 192 | event => data.push(event.data) |
| 193 | recorder.start() |
| 194 | log(recorder.state |
| 195 | + " durante " |
| 196 | + (milisegundos / 1000) |
| 197 | + " segundos…") |
| 198 | let detenido = new Promise( |
| 199 | (resolve, reject) => { |
| 200 | recorder.onstop = resolve |
| 201 | recorder.onerror = |
| 202 | event => reject(event.name) |
| 203 | }) |
| 204 | let grabado = |
| 205 | espera(milisegundos) |
| 206 | .then(() => recorder.state |
| 207 | === "recording" |
| 208 | && recorder.stop() |
| 209 | ) |
| 210 | |
| 211 | return Promise.all([ |
| 212 | detenido, |
| 213 | grabado |
| 214 | ]) |
| 215 | .then(() => data) |
| 216 | } |
| 217 | |
| 218 | function detiene(stream) { |
| 219 | stream.getTracks().forEach( |
| 220 | track => track.stop()) |
| 221 | } |
| 222 | |
| 223 | function log(msg) { |
| 224 | mensajes.innerHTML += |
| 225 | msg + "<br>" |
| 226 | } |
| 227 | |
| 228 | function espera(milisegundos) { |
| 229 | return new Promise( |
| 230 | resolve => setTimeout( |
| 231 | resolve, milisegundos)) |
| 232 | } |
| 233 | |
| 234 | </script> |
| 235 | |
| 236 | </body> |
| 237 | |
| 238 | </html> |
En esta lección se revisaron:
Acceso al GPS.
Acceso a la cámara.
Acceso a los archivos.