Endereço original: github.com/whinc/blog/…
Recentemente recebi uma solicitação para postar comentários: os usuários inserem comentários e podem tirar fotos ou selecionar fotos do álbum para enviar, o que significa que comentários de texto e imagem são suportados. Ele precisa ser implementado no H5 e nos miniprogramas ao mesmo tempo. Este requisito requer muitos locais para processar imagens. Este artigo faz um resumo da prática de processamento de imagens no final do H5. O código do projeto é baseado no framework Vue. Para evitar ser afetado pelo framework, alterei todo o código para a implementação da API nativa para explicação. , corte, progresso de upload, etc.) no código do projeto aqui, omita-o e introduza apenas as principais ideias e códigos relacionados ao processamento de imagem. A implementação do miniprograma é semelhante ao H5 e não será repetida. O código de implementação do miniprograma está anexado no final do artigo.
FotografiaUse a tag <input>, defina type como file para selecionar o arquivo, defina accept como image/* para selecionar o tipo de arquivo e a câmera e defina multiple para suportar seleções múltiplas. Ouça o evento change para obter a lista de arquivos selecionados, cada arquivo é do tipo 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(arquivo => console.log('nome do arquivo:', arquivo.nome)) } document.querySelector('input').addEventListener('alterar', onFileChange) </script>Visualização da imagem
O método URL.createObjectURL pode criar um caminho de URL local apontando para o objeto de recurso local. Esta interface é usada abaixo para criar o endereço da imagem selecionada e exibi-la.
função onFileChange (evento) { const arquivos = Array.prototype.slice.call (event.target.files) const arquivo = arquivos [0] document.querySelector ('img').src = window.URL.createObjectURL (arquivo) }Rotação de imagem
As fotos tiradas com uma câmera podem ser giradas devido à direção em que a câmera é segurada ao fotografar e precisam ser corrigidas. A correção da rotação requer o conhecimento das informações de rotação da imagem. Aqui usamos uma biblioteca chamada exif-js, que pode ler os metadados EXIF da imagem, incluindo a direção da câmera ao fotografar. informações da imagem podem ser calculadas.
A seguir está o bit do sinalizador de rotação EXIF. Existem 8 tipos no total, mas ao fotografar através da câmera, apenas 1, 3, 6 e 8 podem ser gerados, que correspondem respectivamente à rotação normal da câmera, 180° no sentido horário. , rotação de 90° no sentido anti-horário e rotação no sentido horário. Foto tirada a 90°.
Portanto, para corrigir o ângulo de rotação da imagem, basta ler o sinalizador de rotação EXIF da imagem, determinar o ângulo de rotação, girar a imagem na tela e reexportar uma nova imagem. Em relação à operação de rotação da tela, você pode consultar o artigo "Rotação da imagem da tela e desbloqueio da postura de inversão". A função a seguir implementa a correção do ângulo de rotação do arquivo de imagem, recebe um arquivo de imagem e retorna o novo arquivo de imagem corrigido.
/** * Corrigir problema de ângulo de rotação da imagem * @param {file} imagem original * @return {Promise} promessa resolvida Retorna a nova imagem corrigida */function fixImageOrientation (file) { return new Promise((resolve, rejeitar) => { // Obtenha a imagem const img = new Image(); img.src = window.URL.createObjectURL(file); img.onload = () => { // Obtenha os metadados da imagem (variáveis EXIF são variáveis globais expostas pela biblioteca exif-js introduzida) EXIF.getData(img, function() { // Obtenha o sinalizador de rotação da imagem var orientação = EXIF.getTag(this, Orientation); // Gira a imagem na tela de acordo com o ângulo de rotação if (orientação === 3 || orientação === 6 || orientação === 8) { const canvas = document.createElement(canvas); (180 * Math.PI) / 180); img.width, img.height); break; case 6: // Girar 90° canvas.width = img.height = img.width; ctx.drawImage(img, 0, -img.height, img.width, img.height); Girar -90° canvas.width = img.height; canvas.height = img.width; .width, img.height); break; // Retorna a nova imagem canvas.toBlob(file => resolve(file), 'imagem/jpeg', 0.92) } else { return resolve(arquivo);Compressão de imagem
Hoje em dia, o efeito de câmera dos celulares está cada vez melhor e, com isso, o tamanho das fotos aumentou, podendo facilmente chegar a alguns MB ou até mais de dez MB. O upload direto da imagem original é lento e fácil de carregar. , e o plano de fundo também tem restrições quanto ao tamanho do corpo da solicitação, o carregamento subsequente da exibição da imagem também será mais lento. Esses problemas podem ser resolvidos se o front-end compactar as imagens e depois carregá-las.
A função a seguir implementa a compactação de imagem. O princípio é desenhar a imagem dimensionada na tela e, finalmente, exportar a imagem compactada da tela. Existem duas maneiras de controlar a compactação da imagem: uma é controlar a taxa de zoom da imagem e a outra é controlar a qualidade da imagem exportada.
/** * Imagem compactada * @param {file} Imagem de entrada * @returns {Promise} promessa resolvida Retorna a nova imagem compactada */function compressImage(file) { return new Promise((resolve, rejeitar) => { // Obter a imagem (carregar a imagem é para obter a largura e a altura da imagem) const img = new img.src = window.URL.createObjectURL(file); rejeitar(erro); img.onload = () => { // Largura e altura da tela const canvasWidth = document.documentElement.clientWidth * window.devicePixelRatio; factor // Aqui eu tomo os maiores fatores de escala horizontal e vertical como o fator de escala, de modo a garantir que todo o conteúdo da imagem esteja visível const scaleX = canvasWidth / img.width; const scaleY = canvasHeight / img.height; const scale = Math.min(scaleX, scaleY); // Dimensione a imagem original de acordo com o fator de escala e desenhe-a na tela const canvas = document.createElement; ('const ctx = canvas.getContext(2d); canvas.width = canvasWidth; img.width * escala; const altura da imagem = img.altura * escala; const dx = (largura da tela - largura da imagem) / 2; ); // Exporta nova imagem // Especifique o tipo MIME da imagem como 'image/jpeg', passe qualidade Controlar a qualidade das imagens exportadas e implementar a compactação de imagem const quality = 0.92 canvas.toBlob(file => resolve(tempFile), image/jpeg, quality } });},Carregamento de imagem
Crie dados de formulário por meio de FormData e inicie uma solicitação POST ajax. A função a seguir implementa o upload de arquivos.
Nota: Ao enviar dados FormData, o navegador definirá automaticamente o Content-Type com um valor apropriado. Não há necessidade de definir o Content-Type, caso contrário, um erro será relatado porque o limite do delimitador do corpo da solicitação HTTP é gerado pelo navegador. e não pode ser definido manualmente.
/** * Carregar arquivo* @param {Arquivo} arquivo Arquivo a ser carregado* @returns {Promise} Retorna promessa resolvida se o upload for bem sucedido, caso contrário retorna promessa rejeitada */function uploadFile (file) { return new Promise((resolve , rejeitar) = > { // Preparar dados do formulário const formData = new FormData() formData.append('file', file) // Enviar solicitação const xhr = new XMLHttpRequest() xhr.open('POST', uploadUrl) xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { resolve(JSON.parse(this.responseText)) } else { rejeitar(this.responseText) } } xhr.send(formData) })}resumo
Com as funções auxiliares acima, o processamento é muito mais simples. O código de chamada final é o seguinte:
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] // Corrige a rotação da imagem fixImageOrientation(file).then(file2 => { // Cria uma visualização Imagem document.querySelector('img').src = window.URL.createObjectURL(file2) // Retorno da compactação compressImage(file2) }).then(file3 => { // Atualizar imagem de visualização document.querySelector('img').src = window.URL.createObjectURL(file3) // Upload return uploadFile(file3) }).then(data => { console.log('Upload bem-sucedido') }).catch(error => { console.error('Falha no upload') })}
H5 fornece uma interface para processamento de arquivos. Com a ajuda do canvas, o processamento complexo de imagens pode ser implementado no navegador. Este artigo resume algumas práticas de processamento de imagens no cenário de upload de imagens em H5 no terminal móvel. referência parcial ao encontrar necessidades semelhantes no futuro.
Em anexo está uma pequena referência de implementação do programa
// Tire fotos wx.chooseImage({ sourceType: [camera], sucesso: ({ tempFiles }) => { const file = tempFiles[0] // Processar imagens }});/** * Compactar imagens* @param { Object } params * filePath: String O caminho da imagem de entrada * sucesso: Função Chamada de volta quando a compactação é bem-sucedida e retorna o novo caminho da imagem compactada * fail: Função Retorno de chamada quando a compactação falha */compressImage({ filePath, Success, Fail }) { // Obtenha a largura e altura da imagem wx.getImageInfo({ src: filePath, Success: ({ width, height }) => { const systemInfo = wx .getSystemInfoSync(); const canvasWidth = systemInfo.screenWidth; Atualize o tamanho da tela this.setData({ canvasWidth, canvasHeight }) // Calcula a proporção de escala const scaleX = canvasWidth / width; const scaleY = canvasHeight / height; * scale ; const imageHeight = height * scale; // Desenha a imagem dimensionada para a tela const ctx = wx.createCanvasContext(hidden-canvas); dx = (canvasWidth - imageWidth) / 2; let dy = (canvasHeight - imageHeight) / 2; Imagens compactadas em arquivos temporários wx.canvasToTempFilePath({ canvasId: hidden-canvas, width: canvasWidth, altura: canvasHeight, destWidth: canvasWidth, destHeight: canvasHeight, fileType: jpg, qualidade: 0,92, sucesso: ({ tempFilePath }) => { // Ocultar a tela this.setData({ canvasWidth: 0, canvasHeight: 0 } ) // Compactação concluída com sucesso({ tempFilePath } }, fail: error => { // Ocultar canvas this.setData({ canvasWidth: 0, canvasHeight: 0 }) fail(error);}/** * Carregar arquivo*/uploadFile({ uploadUrl, filePath, onData, onError }) { wx.uploadFile({ url: uploadUrl filePath: filePath, nome: arquivo, cabeçalho: { Cookie: cookie }, sucesso: res => { if (res.statusCode === 200) { onData (res.data) } else { onError (res); onError(erro); } });}Resumir
O texto acima é o HTML5 e um pequeno programa introduzido pelo editor para realizar as funções de rotação, compactação e upload de imagens. Espero que seja útil para você. Se você tiver alguma dúvida, deixe-me uma mensagem e o editor responderá. você na hora. Gostaria também de agradecer a todos pelo apoio ao site de artes marciais VeVb!