使用JavaScript将图像裁剪为特定的长宽比
在这3分钟的教程中,我们将编写一个微型JavaScript函数,该函数可以帮助我们将图像裁剪为各种纵横比。超级有用,可用于在将照片发布到社交媒体时间轴之前上传照片或上传个人资料照片,因为这些照片通常需要具有一定的长宽比。
在本教程中,我们将通过修改图像数据。例如,当用户要上传图像时,我们会将其裁剪为特定的宽高比。如果我们只想以特定的长宽比显示图像,则可以使用仅CSS的解决方案。
加载图像数据
首先,我们需要一个源图像。让我们使用通用图像URL作为源。
const imageURL = 'path/to/our/image.jpeg';
要裁剪图像,我们需要访问实际的图像数据。我们可以通过将URL加载到<img>
元素中来获取这些数据。
const inputImage = new Image();
inputImage.src = imageURL;
下一步是将图像绘制到<canvas>
,画布将允许我们修改图像数据。我们将onload
在设置之前添加回调,src
这样我们就可以捕获加载图像的那一刻。
// 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;
运行此代码会导致<canvas>
呈现与位于的图片相同的图片imageURL
。
将图像裁切成正方形的长宽比
现在我们已经可以访问图像数据了,我们可以开始对其进行操作了。
让我们从方形作物开始。方形作物的纵横比为1:1。这意味着输出图像的每一侧都具有相同的长度。我们可以用数值的长宽比表示它1
。200×200图像1
的宽高比为,可以通过将宽度和高度除以等于1.333
(400/300)的方式来计算400×300图像的宽高比。
让我们编辑代码并查看结果。
// 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裁剪功能
最后,我们将代码转换为可重用的函数,以便我们可以快速裁剪具有各种裁剪纵横比的图像。我们的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
函数可以这样调用:
crop('path/to/our/image.jpeg', 1)
或者,要获得“ 16:9”的收成:
crop('path/to/our/image.jpeg', 16/9)
当函数返回a时,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 canvas API和一些基本数学运算,我们构建了一个微小的裁切助手功能,使您可以轻松快速地裁切各种纵横比的图像。这有助于我们为社交媒体帖子,个人资料图片,熟悉的文档尺寸或其他流行的媒体格式准备图像。
为了使文章简洁,我们当前的解决方案未涵盖以下情况:
- 浏览器被移动照片EXIF方向标头所迷惑。
- 移动设备上的画布内存溢出,以获取非常大的图像。
- 缩小图像时图像质量差。
如果您需要针对这些问题的解决方案,则可以探索Doka,它是一种易于使用的图像编辑器,可以解决这些极端情况,并具有多种附加功能。
侵删请致信站长
西楼网 » 使用JavaScript将图像裁剪为特定的长宽比