Accesso alla fotocamera
Anche se con HTML5 è stata introdotta la possibilità di accedere a gran parte dell'hardware del dispositivo, scattare una foto da un'applicazione WEB può essere una operazione piuttosto complicata. Ci sono infatti numerosi parametri da tenere in considerazione, tra cui anche problemi di permessi (da richiede all'utente), differenza tra vari dispositivi e non ultima lo stato di alcune API (es. ImageCapture è ancora considerata "Experimental" ).
In questo articolo useremo un approccio alternativo che ci permettere di ignorare tutti i problemi elencati in precedenza delegando lo scatto della foto all'applicazione di sistema. Di contro perderemo completamente la possibilità di impostare le opzioni relative allo scatto (risoluzione, aspect ratio, ecc.)
Scattare la foto
Quello che andremo a fare è semplicemente utilizzare la funzione di upload predefinita del browser. Infatti creando un tag INPUT
e andando a specificare che ci interessano solo le immagini il browser mobile chiederà all'utente se leggere l'immagine dalla galleria o scattare una nuova foto. L'idea è quella di creare al volo il tag INPUT
e simularne il click:
// Tutto il codice è riferito a ExtJS 7.7 con toolkit modern
// ma può essere facilmente adattato a qualsiasi versione
const fileInput = Ext.dom.Helper.createDom({
tag: 'input',
type: 'file',
// Questo indica che vogliamo solo delle immagini
accept: 'image/*'
});
fileInput.click();
Visualizzare l'anteprima
Una volta che l'utente ha scattato la foto possiamo visualizzarne una anteprima usando il componente Ext.Img
(è anche possibile usare direttamente Ext.Component
con un tag IMG
). Per farlo dobbiamo agganciare un evento change
al tag INPUT
creato in precedenza:
// recupera un riferimento al componente Ext.Img
const pic = this.lookup('preview');
// Codice dello snippet precedente...
const fileInput = ....;
// Aggancia l'evento change
fileInput.addEventListener('change', () => {
// L'oggetto fileInput prevede la selezione multipla
// ma siccome non la stiamo usando prendiamo il primo file
if (fileInput.files && fileInput.files[0]) {
// Per trasferire l'immagine dal fileInput al tag IMG
// usiamo la classe JavaScript FileReader
let reader = new FileReader();
// Visto che la lettura tramite readAsDataURL è asincrona
// usiamo l'evento onload per assicurarci che sia terminata
reader.onload = function(e) {
pic.setSrc(e.target.result);
};
reader.readAsDataURL(fileInput.files[0]);
}
});
Upload sul server
A questo punto, una volta caricata l'immagine e visualizzata l'anteprima, è possibile eseguire l'upload sul server. Per farlo useremo l'oggetto JavaScript FormData
sul quale possiamo caricare oltre all'immagine una serie di campi che ci interessa spedire al server.
La form può successivamente essere spedita usando Ext.Ajax
:
const formData = new FormData();
// Uno o più campi custom che ci interessa inviare al server
formData.append('customData', customData);
// Volendo possiamo inviare il nome del file
formData.append('filename', fileInput.files[0].name);
// In questo modo inseriamo il file nella form
formData.append('content', fileInput.files[0]);
// Esegue la chiamata Ajax
Ext.Ajax.request({
url: '/api/upload',
rawData: formData,
headers: {
// Fa in modo di usare Content-Type dell'oggetto FormData
'Content-Type': null
}
});
Conclusioni
Come detto in precedenza ci sono altri modi per fare la stessa cosa avendo in più il pieno controllo dello scatto, ma quello presentato è sicuramente il più semplice.
È possibile vedere l'esempio completo su Sencha fiddle.