Ursprüngliche Adresse: github.com/whinc/blog/…
Vor kurzem haben wir eine Anfrage zum Posten von Kommentaren erhalten: Benutzer geben Kommentare ein und können Fotos machen oder Bilder aus dem Album zum Hochladen auswählen, was bedeutet, dass Text- und Bildkommentare unterstützt werden. Es muss sowohl in H5- als auch in Mini-Programmen gleichzeitig implementiert werden. Diese Anforderung erfordert viele Orte zur Verarbeitung von Bildern. Dieser Artikel gibt einen Überblick über die Bildverarbeitungspraxis auf der H5-Seite. Der Projektcode basiert auf dem Vue-Framework. Um eine Beeinträchtigung durch das Framework zu vermeiden, habe ich den gesamten Code zur Erläuterung auf die native API-Implementierung umgestellt. Gleichzeitig gibt es viele weitere zusätzliche Details und Funktionen (Vorschau, Zuschneiden). , Upload-Fortschritt usw.) im Projektcode weglassen und nur die wichtigsten Ideen und Codes im Zusammenhang mit der Bildverarbeitung vorstellen. Die Implementierung des Miniprogramms ähnelt der von H5 und wird nicht wiederholt. Der Implementierungscode des Miniprogramms ist am Ende des Artikels angehängt.
FotoVerwenden Sie das <input>-Tag, legen Sie „type“ auf „file“ fest, um die Datei auszuwählen, legen Sie „accept“ auf „image/*“ fest, um den Dateityp und die Kamera auszuwählen, und legen Sie „multiple“ fest, um Mehrfachauswahlen zu unterstützen. Hören Sie sich das Änderungsereignis an, um die ausgewählte Dateiliste abzurufen. Jede Datei ist vom Typ Blob.
<input type=file Accept=image/* multiple /> <img class=preivew /> <script type=text/javascript> function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files ) files.forEach(file => console.log('file name:', file.name)) } document.querySelector('input').addEventListener('change', onFileChange) </script> BildvorschauDie Methode URL.createObjectURL kann einen lokalen URL-Pfad erstellen, der auf das lokale Ressourcenobjekt verweist. Diese Schnittstelle wird unten verwendet, um die Adresse des ausgewählten Bildes zu erstellen und anzuzeigen.
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] document.querySelector('img').src = window.URL.createObjectURL(file) } BilddrehungMit einer Kamera aufgenommene Bilder können aufgrund der Richtung, in der die Kamera beim Aufnehmen gehalten wird, gedreht sein und müssen korrigiert werden. Um die Drehung zu korrigieren, müssen wir die Rotationsinformationen des Bildes kennen. Hier verwenden wir eine Bibliothek namens exif-js, die die EXIF-Metadaten des Bildes lesen kann, einschließlich der Richtung der Kamera beim Aufnehmen Informationen des Bildes können berechnet werden.
Das Folgende ist das EXIF-Rotations-Flag-Bit. Bei der Aufnahme durch die Kamera können jedoch nur 1, 3, 6 und 8 generiert werden, die jeweils der Kameranormalen entsprechen, also 180° im Uhrzeigersinn Drehung, Drehung um 90° gegen den Uhrzeigersinn und Drehung im Uhrzeigersinn, aufgenommen um 90°.
Um den Bilddrehwinkel zu korrigieren, müssen Sie daher nur die EXIF-Rotationsflagge des Bildes lesen, den Drehwinkel bestimmen, das Bild auf der Leinwand drehen und ein neues Bild erneut exportieren. Informationen zum Rotationsvorgang der Leinwand finden Sie im Artikel „Rotation des Leinwandbilds und Entsperren der Flip-Position“. Die folgende Funktion implementiert die Drehwinkelkorrektur der Bilddatei, empfängt eine Bilddatei und gibt die korrigierte neue Bilddatei zurück.
/** * Problem mit dem Bilddrehwinkel behoben * @param {file} Originalbild * @return {Promise} aufgelöstes Versprechen Das korrigierte neue Bild zurückgeben */function fixImageOrientation (file) { return new Promise((resolve, ablehn) => { // Holen Sie sich das Bild const img = new Image(); img.src = window.URL.createObjectURL(file); img.onerror = () => restart(file); img.onload = () => { // Bildmetadaten abrufen (EXIF-Variablen sind globale Variablen, die von der eingeführten exif-js-Bibliothek bereitgestellt werden) EXIF.getData(img, function() { // Bildrotationsflag abrufen var Orientierung = EXIF.getTag(this, Orientation); // Das Bild auf der Leinwand entsprechend dem Drehwinkel drehen if (orientation === 3 || Orientation === 6 || Orientation === 8) { const canvas = document.createElement(canvas); const ctx = canvas.getContext(2d); switch (orientation) { case 3: // 180° drehen canvas.width = img.width; (180 * Math.PI) / 180); ctx.drawImage(img, -img.width, -img.height, img.width, img.height); break; case 6: // 90° drehen canvas.width = img.height; ctx.drawImage(img, 0, -img.height, img.width, img.height); -90° drehen canvas.width = img.height; canvas.height = img.rotate((-90 * Math.PI) / 180); .width, img.height); break } // Das neue Bild zurückgeben. 'image/jpeg', 0,92) } else { return restart(file); }); BildkomprimierungHeutzutage wird der Kameraeffekt von Mobiltelefonen immer besser und damit auch die Größe der Bilder, die leicht einige MB oder sogar mehr als zehn MB erreichen können. Das direkte Hochladen des Originalbilds ist langsam und einfach Wenn dies fehlschlägt und der Hintergrund auch Einschränkungen hinsichtlich der Größe des Anforderungstexts aufweist, wird das anschließende Laden der Bildanzeige ebenfalls langsamer. Wenn das Frontend das Bild komprimiert und dann hochlädt, können diese Probleme gelöst werden.
Die folgende Funktion implementiert die Bildkomprimierung. Das Prinzip besteht darin, das skalierte Bild auf der Leinwand zu zeichnen und schließlich das komprimierte Bild von der Leinwand zu exportieren. Es gibt zwei Möglichkeiten, die Bildkomprimierung zu steuern: Die eine besteht darin, das Zoomverhältnis des Bildes zu steuern, die andere darin, die Qualität des exportierten Bildes zu steuern.
/** * Komprimiertes Bild * @param {file} Eingabebild * @returns {Promise} aufgelöstes Versprechen Gibt das neue komprimierte Bild zurück */function compressImage(file) { return new Promise((resolve,ject) => { // Get das Bild (das Laden des Bildes dient dazu, die Breite und Höhe des Bildes zu ermitteln) const img = new Image(); img.src = window.URL.createObjectURL(file); img.onerror = error => Reject(error); img.onload = () => { // Canvas-Breite und -Höhe const canvasWidth = document.documentElement.clientWidth * window.devicePixelRatio; const canvasHeight = document.documentElement.clientHeight * window.devicePixelRatio; Faktor // Hier nehme ich den größeren horizontalen und vertikalen Skalierungsfaktor als Skalierungsfaktor, um sicherzustellen, dass der gesamte Bildinhalt sichtbar ist const scaleX = canvasWidth / img.width; const ScaleY = CanvasHeight / img.height; const Scale = Math.min(scaleX, ScaleY); // Skalieren Sie das Originalbild entsprechend dem Skalierungsfaktor und zeichnen Sie es auf die Leinwand const Canvas = document.createElement ('canvas'); const ctx = Canvas.getContext(2d); Canvas.width = CanvasWidth; img.width * scale; const imageHeight = img.height * scale; const dx = (canvasWidth - imageHeight) / 2; ctx.drawImage(img, dx, dy, imageWidth, imageHeight ); // Neues Bild exportieren // Geben Sie den Bild-MIME-Typ als „image/jpeg“ an und übergeben Sie die Qualität Kontrollieren Sie die Qualität der exportierten Bilder und implementieren Sie die Bildkomprimierung const quality = 0.92 canvas.toBlob(file => restart(tempFile), image/jpeg, quality }); Bild-UploadErstellen Sie Formulardaten über FormData und initiieren Sie eine Ajax-POST-Anfrage. Die folgende Funktion implementiert das Hochladen von Dateien.
Hinweis: Beim Senden von FormData-Daten setzt der Browser den Content-Type automatisch auf einen geeigneten Wert. Der Content-Type muss nicht festgelegt werden, andernfalls wird ein Fehler gemeldet, da die Begrenzung des HTTP-Anforderungskörpers vom Browser generiert wird und kann nicht manuell eingestellt werden.
/** * Datei hochladen* @param {File} file Hochzuladende Datei* @returns {Promise} Gibt ein aufgelöstes Versprechen zurück, wenn der Upload erfolgreich ist, andernfalls wird ein abgelehntes Versprechen zurückgegeben */function uploadFile (file) { return new Promise((resolve , ablehnen) = > { // Formulardaten vorbereiten const formData = new FormData() formData.append('file', file) // Anfrage senden const xhr = new XMLHttpRequest() xhr.open('POST', uploadUrl) xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { restart(JSON.parse(this.responseText)) } else { Reject(this.responseText) } } xhr.send(formData) })} ZusammenfassungMit den oben genannten Hilfsfunktionen ist die Verarbeitung viel einfacher. Der endgültige Aufrufcode lautet wie folgt:
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] // Bilddrehung korrigieren fixImageOrientation(file).then(file2 => { // Vorschau erstellen Bild document.querySelector('img').src = window.URL.createObjectURL(file2) // Komprimierung return compressImage(file2) }).then(file3 => { // Vorschaubild aktualisieren document.querySelector('img').src = window.URL.createObjectURL(file3) // Upload return uploadFile(file3) }).then(data => { console.log('Upload erfolgreich') }).catch(error => { console.error('Upload failed') })}H5 bietet eine Schnittstelle zum Verarbeiten von Dateien im Browser. Dieser Artikel fasst einige Bildverarbeitungspraktiken im Szenario des Hochladens von Bildern in H5 zusammen teilweise Referenz, wenn in Zukunft ähnliche Bedürfnisse auftreten.
Im Anhang finden Sie eine kleine Referenz zur Programmimplementierung
// Fotos machen wx.chooseImage({ sourceType: [camera], success: ({ tempFiles }) => { const file = tempFiles[0] // Bilder verarbeiten }});/** * Bilder komprimieren* @param { Object } params * filePath: String Der Eingabebildpfad * success: Funktion Wird zurückgerufen, wenn die Komprimierung erfolgreich ist und gibt den neuen komprimierten Bildpfad zurück * fail: Funktion Rückruf, wenn die Komprimierung fehlschlägt */compressImage({ filePath, success, fail }) { // Bildbreite und -höhe abrufen wx.getImageInfo({ src: filePath, success: ({ width, height }) => { const systemInfo = wx .getSystemInfoSync (); const canvasWidth = systemInfo.screenWidth; const canvasHeight = systemInfo.screenHeight; Aktualisieren Sie die Leinwandgröße this.setData({ canvasWidth, canvasHeight }) // Berechnen Sie das Skalierungsverhältnis const scaleX = canvasWidth / width; constscaleY = canvasHeight / height; const imageWidth = width * scale ; const imageHeight = height * scale; // Zeichne das skalierte Bild auf die Leinwand const ctx = wx.createCanvasContext(hidden-canvas); dx = (canvasWidth - imageWidth) / 2; let dy = (canvasHeight - imageHeight) / 2; ctx.drawImage(filePath, dx, dy, imageWidth, imageHeight); ctx.draw(false, () => { // Exportieren Komprimierte Bilder in temporäre Dateien wx.canvasToTempFilePath({ CanvasId: Hidden-Canvas, Breite: CanvasWidth, Höhe: CanvasHeight, destWidth: CanvasWidth, destHeight: CanvasHeight, Dateityp: JPG, Qualität: 0,92, Erfolg: ({ tempFilePath }) => { // Leinwand ausblenden this.setData({ CanvasWidth: 0, CanvasHeight: 0 } ) // Komprimierung erfolgreich abgeschlossen ({ tempFilePath } }, fail: error => { // Leinwand ausblenden this.setData({ CanvasWidth: 0, CanvasHeight: 0 }) fail(error); }, fail: error => { fail(error } }); Datei hochladen*/uploadFile({ uploadUrl, filePath, onData, onError }) { wx.uploadFile({ url: uploadUrl filePath: filePath, name: Datei, Header: { Cookie: Cookie }, Erfolg: res => { if (res.statusCode === 200) { onData(res.data) } else { onError(res } }, fail: error => { onError(error);} });} ZusammenfassenDas Obige ist das vom Herausgeber eingeführte HTML5-Programm zum Realisieren der Funktionen zum Drehen, Komprimieren und Hochladen von Bildern. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht Sie rechtzeitig. Ich möchte mich auch bei allen für die Unterstützung der VeVb-Kampfsport-Website bedanken!