원본 주소: github.com/whinc/blog/…
최근 댓글 게시 요청을 받았습니다. 사용자는 댓글을 입력하고 사진을 찍거나 앨범에서 사진을 선택하여 업로드할 수 있습니다. 이는 텍스트 및 사진 댓글이 지원된다는 의미입니다. H5와 미니 프로그램 모두에서 동시에 구현되어야 합니다. 이 요구 사항은 이미지를 처리하는 데 많은 장소가 필요합니다. 이 문서에서는 H5 측의 이미지 처리 실습을 요약합니다. 프로젝트 코드는 Vue 프레임워크를 기반으로 하며, 설명을 위해 모든 코드를 네이티브 API 구현으로 변경했습니다. , 업로드 진행 등) 여기서는 프로젝트 코드를 생략하고 이미지 처리와 관련된 핵심 아이디어와 코드만 소개합니다. 미니 프로그램의 구현은 H5와 유사하며, 미니 프로그램의 구현 코드는 기사 마지막 부분에 첨부되어 있습니다.
사진<input> 태그를 사용하고, 유형을 file로 설정하여 파일을 선택하고, accept를 image/*로 설정하여 파일 유형과 카메라를 선택하고, multiple을 설정하여 다중 선택을 지원하세요. 선택한 파일 목록을 가져오기 위해 변경 이벤트를 수신합니다. 각 파일은 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)) } document.querySelector('input').addEventListener('change', onFileChange) </script>사진 미리보기
URL.createObjectURL 메소드는 로컬 자원 객체를 가리키는 로컬 URL 경로를 생성할 수 있습니다. 이 인터페이스는 아래에서 선택한 이미지의 주소를 생성하고 표시하는 데 사용됩니다.
function onFileChange (이벤트) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] document.querySelector('img').src = window.URL.createObjectURL(file) }그림 회전
카메라로 촬영한 사진은 촬영 시 카메라를 잡는 방향으로 인해 회전될 수 있으므로 보정이 필요합니다. 회전을 수정하려면 이미지의 회전 정보를 알아야 합니다. 여기서는 촬영 시 카메라 방향을 포함하여 이미지의 EXIF 메타데이터를 읽을 수 있는 라이브러리를 사용합니다. 이미지의 정보를 계산할 수 있습니다.
다음은 EXIF 회전 플래그 비트로 총 8가지가 있는데, 카메라를 통해 촬영할 경우 각각 카메라 노멀, 시계방향 180°에 해당하는 1, 3, 6, 8만 생성할 수 있다. 회전, 시계 반대 방향 90° 회전, 시계 방향 회전 90°에서 찍은 사진입니다.
따라서 이미지 회전 각도를 수정하려면 이미지의 EXIF 회전 플래그를 읽고 회전 각도를 결정한 후 캔버스에서 이미지를 회전시키고 새 이미지를 다시 내보내면 됩니다. 캔버스의 회전 작업에 대해서는 "캔버스 이미지 회전 및 뒤집기 자세 잠금 해제" 기사를 참조할 수 있습니다. 다음 함수는 이미지 파일의 회전 각도 수정을 구현하고, 이미지 파일을 수신하고, 수정된 새 이미지 파일을 반환합니다.
/** * 이미지 회전 각도 문제 수정 * @param {file} 원본 이미지 * @return {Promise} 해결됨 promise 수정된 새 이미지 반환 */function fixImageOrientation (file) { return new Promise((resolve, Reject) => { // 이미지 가져오기 const img = new Image() img.src = window.URL.createObjectURL(file) img.onerror = () => 해결(file); img.onload = () => { // 이미지 메타데이터를 가져옵니다(EXIF 변수는 도입된 EXIF-js 라이브러리에 의해 노출되는 전역 변수입니다) EXIF.getData(img, function() { // 이미지 회전 플래그를 가져옵니다 var orientation = EXIF.getTag(this, Orientation); // 회전 각도에 따라 캔버스 위의 이미지를 회전합니다. if (orientation === 3 || orientation === 6 || orientation === 8) { const canvas = document.createElement(canvas); const ctx = canvas.getContext(2d); 스위치(방향) { 사례 3: // 180° 회전 canvas.width = img.width; (180 * 수학.PI) / 180) ctx.drawImage(img, -img.width, -img.height, img.width, img.height); break; 사례 6: // 90° 회전 canvas.width = img.height; canvas.height = img.rotate((90 * Math.PI) / 180); ctx.drawImage(img, 0, -img.height, img.width, img.height) 사례 8: // -90° 회전 canvas.width = img.height; canvas.height = img.width; ctx.rotate((-90 * Math.PI) / 180); .width, img.height); break; } // 새 이미지를 반환합니다. canvas.toBlob(file => 해결(file), 'image/jpeg', 0.92) } else { return 해결(파일) } });이미지 압축
요즘에는 휴대폰의 카메라 효과가 점점 좋아지고 있으며, 이로 인해 사진 크기도 늘어나서 쉽게 몇 MB, 심지어는 10MB 이상이 될 수도 있습니다. 원본 사진을 직접 업로드하는 것은 느리고 업로드하기 쉽습니다. 실패하고 배경에도 요청 본문 크기에 제한이 있으므로 이후의 이미지 표시 로드도 느려집니다. 프런트 엔드에서 이미지를 압축한 후 업로드하면 이러한 문제가 해결될 수 있습니다.
다음 함수는 이미지 압축을 구현하는 원리로, 크기가 조정된 이미지를 캔버스에 그리고 마지막으로 압축된 이미지를 캔버스에서 내보내는 것입니다. 이미지 압축을 제어하는 방법에는 두 가지가 있습니다. 하나는 이미지의 확대/축소 비율을 제어하는 것이고, 다른 하나는 내보낸 이미지의 품질을 제어하는 것입니다.
/** * 압축된 이미지 * @param {file} 입력 이미지 * @returns {Promise} 해결된 promise 새 압축된 이미지 반환 */function 압축Image(file) { return new Promise((resolve, Reject) => { // 가져오기 이미지(이미지를 로드하는 것은 이미지의 너비와 높이를 가져오는 것입니다) const img = new Image() = window.URL.createObjectURL(file); accept(error); img.onload = () => { // 캔버스 너비와 높이 const canvasWidth = document.documentElement.clientWidth * window.devicePixelRatio; const canvasHeight = document.documentElement.clientHeight * window.devicePixelRatio; Factor // 여기서는 모든 이미지 내용이 표시되도록 하기 위해 더 큰 수평 및 수직 스케일링 인자를 스케일링 인자로 사용합니다. const scaleX = canvasWidth / img.width; const scaleY = canvasHeight / img.height; const scale = Math.min(scaleX, scaleY); // 배율에 따라 원본 이미지의 크기를 조정하고 캔버스에 그립니다. (' 캔버스'); const ctx = canvas.getContext(2d); canvas.width = canvas.height = canvasHeight; img.width * scale; const imageHeight = img.height * scale; const dx = (canvasWidth - imageWidth) / 2; const dy = (canvasHeight - imageHeight) / 2; ); // 새 이미지 내보내기 // 이미지 MIME 유형을 'image/jpeg'로 지정하고 품질을 통과합니다. 내보낸 이미지의 품질을 제어하고 이미지 압축을 구현합니다. const quality = 0.92 canvas.toBlob(file =>solve(tempFile), image/jpeg, quality) });};이미지 업로드
FormData를 통해 양식 데이터를 생성하고 ajax POST 요청을 시작합니다. 다음 함수는 파일 업로드를 구현합니다.
참고: FormData 데이터를 보낼 때 브라우저는 자동으로 Content-Type을 적절한 값으로 설정합니다. Content-Type을 설정할 필요가 없습니다. 그렇지 않으면 HTTP 요청 본문 구분 기호 경계가 브라우저에 의해 생성되기 때문에 오류가 보고됩니다. 수동으로 설정할 수 없습니다.
/** * 파일 업로드* @param {File} file 업로드할 파일* @returns {Promise} 업로드가 성공하면 해결된 Promise를 반환하고, 그렇지 않으면 거부된 Promise를 반환합니다. */function uploadFile(file) { return new Promise((resolve , accept) = > { // 양식 데이터 준비 const formData = new FormData() formData.append('file', file) // 요청 제출 const xhr = new XMLHttpRequest() xhr.open('POST', uploadUrl) xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { 해결(JSON.parse(this.responseText)) } else { 거부(this.responseText) } } xhr.send(formData) })}요약
위의 보조 기능을 사용하면 처리가 훨씬 간단해집니다. 최종 호출 코드는 다음과 같습니다.
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] // 이미지 회전 수정 fixImageOrientation(file).then(file2 => { // 미리보기 생성 Image document.querySelector('img').src = window.URL.createObjectURL(file2) // 압축 반환 압축 이미지(file2) }).then(file3 => { // 미리보기 이미지 업데이트 document.querySelector('img').src = window.URL.createObjectURL(file3) // 업로드 return uploadFile(file3) }).then(data => { console.log('업로드 성공') }).catch(error => { console.error('업로드 실패') })}
H5는 파일 처리를 위한 인터페이스를 제공하며, 브라우저에서 복잡한 이미지 처리를 구현할 수 있습니다. 이 기사에서는 모바일 단말기에서 H5에 이미지를 업로드하는 시나리오에서 몇 가지 이미지 처리 사례를 요약하여 사용할 수 있습니다. 향후 유사한 요구 사항이 발생할 때 부분적으로 참조하세요.
첨부된 내용은 작은 프로그램 구현 참고자료입니다.
// 사진 찍기 wx.chooseImage({ sourceType: [camera], Success: ({ tempFiles }) => { const file = tempFiles[0] // 이미지 처리 }});/** * 이미지 압축* @param { Object } params * filePath: 문자열 입력 이미지 경로 * Success: 함수 압축에 성공하면 다시 호출되고 새 압축 이미지 경로를 반환합니다. * failure: 함수 압축 실패 시 콜백 */compressImage({ filePath, 성공, 실패 }) { // 이미지 너비 및 높이 가져오기 wx.getImageInfo({ src: filePath, 성공: ({ width, height }) => { const systemInfo = wx .getSystemInfoSync(); const canvasWidth = systemInfo.screenWidth; const canvasHeight = systemInfo.screenHeight; 캔버스 크기 업데이트 this.setData({ canvasWidth, canvasHeight }) // 크기 조정 비율 계산 const scaleX = canvasWidth / width; const scaleY = canvasHeight / height; const scale = Math.min(scaleX, scaleY); * scale ; const imageHeight = height * scale; // 크기가 조정된 이미지를 캔버스에 그립니다. const ctx = wx.createCanvasContext(hidden-canvas); dx = (canvasWidth - imageWidth) / 2; let dy = (canvasHeight - imageHeight) / 2; ctx.drawImage(filePath, dx, dy, imageWidth, imageHeight); 이미지를 임시 파일로 압축 wx.canvasToTempFilePath({ canvasId: Hidden-canvas, width: canvasWidth, height: canvasHeight, destWidth: canvasWidth, destHeight: canvasHeight, fileType: jpg, quality: 0.92, Success: ({ tempFilePath }) => { // 캔버스 숨기기 this.setData({ canvasWidth: 0, canvasHeight: 0 } ) // 압축 완료 성공({ tempFilePath }) }, 실패: error => { // 캔버스 숨기기 this.setData({ canvasWidth: 0, canvasHeight: 0 }) 실패(오류) } }) }), 실패: 오류 => { 실패(오류) } ); 파일 업로드*/uploadFile({ uploadUrl, filePath, onData, onError }) { wx.uploadFile({ url: uploadUrl filePath: filePath, name: 파일, 헤더: { 쿠키: 쿠키 }, 성공: res => { if (res.statusCode === 200) { onData(res.data) } else { onError(res) } }, 실패: 오류 => { onError(오류) } });}요약
위 내용은 사진 회전, 압축, 업로드 기능을 구현하기 위해 편집자가 소개한 HTML5 및 작은 프로그램입니다. 궁금한 사항이 있으시면 메시지를 남겨주시면 편집자가 답변해 드리겠습니다. 당신은 시간에. 또한 VeVb 무술 웹사이트를 지원해 주신 모든 분들께 감사드립니다!