Cover

这里我们讨论的图像截取部分是指从一个完整的大图中截取一小部分出来。当然,使用 js 实现。

这边文章基本整理自Cropping images with Javascript, 添加了一些我的评论

例如,我们要从这样的大图中:

大图

截取出

小图

使用 H5 中的 canvas 可以简单地解决这个问题。

1 1. 载入原图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var loadTimer;
var imgObject = new Image();
imgObject.src = "images/fozzie.jpg";
imgObject.onLoad = onImgLoaded();
function onImgLoaded() {
if (loadTimer != null) clearTimeout(loadTimer);
if (!imgObject.complete) {
loadTimer = setTimeout(function () {
onImgLoaded();
}, 3);
} else {
onPreloadComplete();
}
}

注意这里我们为了演示是读取的图片文件内容,实际上除了图像文件,这里的“图像”还可以是其他形式,例如 video 元素,别的 canvas 等。

2 2. 当图片完成载入以后,重新绘制你要截取的那一部分

1
2
3
4
5
6
function onPreloadComplete(){
//call the methods that will create a 64-bit version of thumbnail here.
var newImg = getImagePortion(imgObject, 120, 150, 150, 80, 2);
//place image in appropriate div
document.getElementById("images").innerHTML = "<img alt="" src=""+newImg+"" />";
}

这个onPreloadComplete函数会在图像载入完成以后调用。在这个函数中我们会调用实际完成图片截取的函数getImagePortion

3 3. 图像截取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
getImagePortion(imgObj, newWidth, newHeight, startX, startY, ratio){
/* the parameters: - the image element - the new width - the new height - the x point we start taking pixels - the y point we start taking pixels - the ratio */
//set up canvas for thumbnail
var tnCanvas = document.createElement('canvas');
var tnCanvasContext = canvas.getContext('2d');
tnCanvas.width = newWidth; tnCanvas.height = newHeight;

/* use the sourceCanvas to duplicate the entire image. This step was crucial for iOS4 and under devices. Follow the link at the end of this post to see what happens when you don’t do this */
var bufferCanvas = document.createElement('canvas');
var bufferContext = bufferCanvas.getContext('2d');
bufferCanvas.width = imgObj.width;
bufferCanvas.height = imgObj.height;
bufferContext.drawImage(imgObj, 0, 0);

/* now we use the drawImage method to take the pixels from our bufferCanvas and draw them into our thumbnail canvas */
tnCanvasContext.drawImage(bufferCanvas, startX,startY,newWidth * ratio, newHeight * ratio,0,0,newWidth,newHeight);
return tnCanvas.toDataURL();
}

上面的函数时原作者给出的方法,他先将图像完整地画到一个 canvas(bufferCanvas)上,再将这个 canvas 对应的目标区域画到tnCanvas上,根据注释来看,似乎是出于性能或者适配方面的考虑。不过就我在开发桌面端网页时,可以直接将imgObj画到tnCanvas上。