분류 javascript

JavaScript를 사용하여 이미지를 특정 종횡비로 자르기

컨텐츠 정보

  • 조회 434 (작성일 )

본문

이 3 분 자습서에서는 이미지를 다양한 종횡비로 자르는 데 도움이 되는 작은 JavaScript 함수를 작성합니다. 

소셜 미디어 타임 라인에 게시하거나 프로필 사진을 업로드하기 전에 사진을 자르기 전에 종종 가로 세로 비율이 필요하기 때문에 매우 유용합니다.


https://pqina.nl/blog/cropping-images-to-an-aspect-ratio-with-javascript/ 


이 자습서에서는 이미지 데이터를 수정합니다. 예를 들어, 사용자가 이미지를 업로드하려고 할 때 특정 종횡비로 자릅니다. 특정 종횡비로 이미지를 제공하려는 경우 CSS 전용 솔루션을 사용할 수 있습니다.


crop-aspect-ratio.png 


이미지 데이터 로드 


시작하려면 소스 이미지가 필요합니다. 일반적인 이미지 URL을 소스로 사용하겠습니다.


const imageURL = 'path/to/our/image.jpeg'; 


이미지를 자르려면 실제 이미지 데이터에 액세스 해야 합니다. URL을 <img> 요소에 로드하여 이 데이터를 얻을 수 있습니다.


const inputImage = new Image(); inputImage.src = imageURL; 


다음 단계는 <canvas>에 이미지를 그리는 것입니다. 캔버스에서 이미지 데이터를 수정할 수 있습니다. src를 설정하기 직전에 onload 콜백을 추가하여 이미지가 로드 된 순간을 캡처 할 수 있습니다.


// this image will hold our source image data const inputImage = new Image(); // we want to wait for our image to load inputImage.onload = () => { // create a canvas that will present the output image const outputImage = document.createElement('canvas'); // set it to the same size as the image outputImage.width = inputImage.naturalWidth; outputImage.height = inputImage.naturalHeight; // draw our image at position 0, 0 on the canvas const ctx = outputImage.getContext('2d'); ctx.drawImage(inputImage, 0, 0); // show both the image and the canvas document.body.appendChild(inputImage); document.body.appendChild(outputImage); }; // start loading our image inputImage.src = imageURL; 


이 코드를 실행하면 이미지 URL에있는 이미지와 동일한 이미지를 나타내는 <canvas>가 생성됩니다.


이미지를 제곱 종횡비로 자르기 


이미지 데이터에 액세스 했으므로 이제 이미지 조작을 시작할 수 있습니다.


정사각형 자르기부터 시작하겠습니다. 정사각형 작물의 종횡비는 1 : 1입니다. 이는 출력 이미지의 각면의 길이가 동일하다는 것을 의미합니다. 이 수치를 1의 종횡비로 나타낼 수 있습니다. 200x200 이미지의 종횡비는 1이고 너비와 높이를 1.333 (400/300)으로 나누어 400x300 이미지의 종횡비를 계산할 수 있습니다.


코드를 수정하고 결과를 봅시다.


// the desired aspect ratio of our output image (width / height) const outputImageAspectRatio = 1; // this image will hold our source image data const inputImage = new Image(); // we want to wait for our image to load inputImage.onload = () => { // let's store the width and height of our image const inputWidth = inputImage.naturalWidth; const inputHeight = inputImage.naturalHeight; // get the aspect ratio of the input image const inputImageAspectRatio = inputWidth / inputHeight; // if it's bigger than our target aspect ratio let outputWidth = inputWidth; let outputHeight = inputHeight; if (inputImageAspectRatio > outputImageAspectRatio) { outputWidth = inputHeight * outputImageAspectRatio; } else if (inputImageAspectRatio < outputImageAspectRatio) { outputHeight = inputHeight / outputImageAspectRatio; } // create a canvas that will present the output image const outputImage = document.createElement('canvas'); // set it to the same size as the image outputImage.width = outputWidth; outputImage.height = outputHeight; // draw our image at position 0, 0 on the canvas const ctx = outputImage.getContext('2d'); ctx.drawImage(inputImage, 0, 0); // show both the image and the canvas document.body.appendChild(inputImage); document.body.appendChild(outputImage); }; // start loading our image inputImage.src = imageURL; 


결과는 정사각형 이미지입니다. 하지만 자세히 살펴 보겠습니다. 자르기가 입력 이미지의 중앙에 위치하지 않은 것 같습니다. drawImage 호출을 업데이트하지 않았기 때문입니다. drawImage 호출은 이미지를 그릴 때 3 개 이상의 인수, inputImage 및 x 및 y 위치를 사용합니다.


입력 이미지는 여전히 0, 0 위치에 그려집니다. 왼쪽 상단 자르기 대신 중앙 자르기를 얻기 위해 조정해야 합니다.


이렇게 하려면 이미지를 약간 왼쪽으로 이동해야 합니다. 입력 이미지의 너비가 400 픽셀이고 출력 이미지의 너비가 300 픽셀이라고 가정하면 중앙에 입력 이미지를 왼쪽으로 50 픽셀 (음수 50 픽셀)로 이동해야 합니다. -50 픽셀은 300에서 400을 2로 나눈 값입니다.이 결과는 다음 코드 조각입니다.


const outputX = (outputWidth - inputWidth) * .5 


코드 스니펫을 업데이트하겠습니다. x와 y 오프셋에 동일한 코드를 사용할 수 있습니다.


// the desired aspect ratio of our output image (width / height) const outputImageAspectRatio = 1; // this image will hold our source image data const inputImage = new Image(); // we want to wait for our image to load inputImage.onload = () => { // let's store the width and height of our image const inputWidth = inputImage.naturalWidth; const inputHeight = inputImage.naturalHeight; // get the aspect ratio of the input image const inputImageAspectRatio = inputWidth / inputHeight; // if it's bigger than our target aspect ratio let outputWidth = inputWidth; let outputHeight = inputHeight; if (inputImageAspectRatio > outputImageAspectRatio) { outputWidth = inputHeight * outputImageAspectRatio; } else if (inputImageAspectRatio < outputImageAspectRatio) { outputHeight = inputHeight / outputImageAspectRatio; } // calculate the position to draw the image at const outputX = (outputWidth - inputWidth) * .5; const outputY = (outputHeight - inputHeight) * .5; // create a canvas that will present the output image const outputImage = document.createElement('canvas'); // set it to the same size as the image outputImage.width = outputWidth; outputImage.height = outputHeight; // draw our image at position 0, 0 on the canvas const ctx = outputImage.getContext('2d'); ctx.drawImage(inputImage, outputX, outputY); // show both the image and the canvas document.body.appendChild(inputImage); document.body.appendChild(outputImage); }; // start loading our image inputImage.src = imageURL; 


이번 업데이트에서는 자르기가 입력 이미지를 중심으로 합니다.


재사용 가능한 JavaScript 자르기 함수 작성 


마지막 단계로 코드를 재사용 가능한 기능으로 바꾸어 다양한 자르기 종횡비로 이미지를 빠르게 자를 수 있습니다. Google의 JavaScript 스니펫은 정사각형 뿐만 아니라 모든 종횡비에 사용하기에 이미 적합합니다.


/** * @param {string} url - The source image * @param {number} aspectRatio - The aspect ratio * @return {Promise<HTMLCanvasElement>} A Promise that resolves with the resulting image as a canvas element */ function crop(url, aspectRatio) { // we return a Promise that gets resolved with our canvas element return new Promise(resolve => { // this image will hold our source image data const inputImage = new Image(); // we want to wait for our image to load inputImage.onload = () => { // let's store the width and height of our image const inputWidth = inputImage.naturalWidth; const inputHeight = inputImage.naturalHeight; // get the aspect ratio of the input image const inputImageAspectRatio = inputWidth / inputHeight; // if it's bigger than our target aspect ratio let outputWidth = inputWidth; let outputHeight = inputHeight; if (inputImageAspectRatio > aspectRatio) { outputWidth = inputHeight * aspectRatio; } else if (inputImageAspectRatio < aspectRatio) { outputHeight = inputHeight / aspectRatio; } // calculate the position to draw the image at const outputX = (outputWidth - inputWidth) * .5; const outputY = (outputHeight - inputHeight) * .5; // create a canvas that will present the output image const outputImage = document.createElement('canvas'); // set it to the same size as the image outputImage.width = outputWidth; outputImage.height = outputHeight; // draw our image at position 0, 0 on the canvas const ctx = outputImage.getContext('2d'); ctx.drawImage(inputImage, outputX, outputY); resolve(outputImage); }; // start loading our image inputImage.src = url; }) } 


새롭고 반짝이는 자르기 기능은 다음과 같이 호출 할 수 있습니다.


crop('path/to/our/image.jpeg', 1) 


또는 "16 : 9"자르기 :


crop('path/to/our/image.jpeg', 16/9) 


함수가 Promise를 반환하면 다음과 같은 결과를 얻을 수 있습니다.


crop('path/to/our/image.jpeg', 16/9).then(canvas => { // `canvas` is the resulting image }) 


또는 async / await를 사용하십시오.


const canvas = await crop('path/to/our/image.jpeg', 16/9) 


CodePen의 최종 결과 데모보기


결론 


HTML 캔버스 API와 몇 가지 기본 수학을 사용하여 다양한 가로 세로 비율로 이미지를 빠르게 자르기 쉽게 해주는 작은 자르기 도우미 기능을 만듭니다. 이를 통해 소셜 미디어 게시물, 프로필 사진, 친숙한 문서 크기 또는 기타 인기 있는 미디어 형식을 위한 이미지를 준비 할 수 있습니다.


기사를 간결하게 유지하기 위해 현재 솔루션은 다음과 같은 경우를 다루지 않습니다.

  • 모바일 사진 EXIF ​​오리엔테이션 헤더에 의해 혼동되는 브라우저.
  • 매우 큰 이미지를 위해 모바일 장치에서 캔버스 메모리가 넘칩니다.
  • 이미지를 축소 할 때 이미지 품질이 좋지 않습니다.