我正在编写Ionic 3应用程序以拍摄小照片。
我正在使用Camera Preview插件执行此操作:
然后我使用以下方法获取绿色框的坐标:
<div id="mask" style="width:100%;height:100px;border:10px solid rgb(125, 255, 0);" *ngIf="!picture"> </div>
var box = document.getElementById("mask");
var rect = box.getBoundingClientRect();
console.log("MASK: "+rect.left+" "+rect.top+" "+rect.width+" "+rect.height)
然后我使用从包装盒中获得的坐标来裁剪图像以获取图像:
我正在使用以下代码裁剪图像:
generateFromImage(img, x, y, w, h, quality: number = 1, callback) {
var canvas: any = document.createElement("canvas");
var image = new Image();
image.src = img;
image.onload = () => {
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, x+this.offsetX, y+this.offsetY, w*this.scaleX, h*this.scaleY, 0, 0, w, h);
var dataUrl = canvas.toDataURL('image/jpeg', quality);
callback(dataUrl)
}
}
其中x,y,w,h是我从box.getBoundingClientRect()获得的坐标。
如您所见,我不得不引入offsetX,offsetY,scaleX,scaleY来调整坐标,因为它不起作用。
drawImage()参数是sx,sy,sw,sh(源框->来自原始图像的坐标)和x,y,w,h(目标->目标图像的坐标)。我不明白为什么它关闭了。
经过反复试验,我发现以下配置适用于我的iPhone 8:
我怀疑Y坐标差与应用程序工具栏有关。我不知道为什么x关闭,为什么在源和目标上使用相同的w和h不能保持宽高比。
我没有在其他设备上进行测试,但它肯定会失败,因为偏移量和比例因子会有所不同。
为什么会这样?为什么我需要固定坐标?
感谢您的帮助!
答案 0 :(得分:3)
您的主要问题是可能,您没有考虑CSS缩放的问题。
我们在 drawImage 中使用的坐标是相对于图像的自然尺寸(即媒体之一,而不是的)。这意味着您不能直接从渲染的转换矩阵(getBoundingClientRect)到媒体的矩阵。
首先需要确定CSS已应用的比例,以便将屏幕空间坐标转换为媒体空间。
var img_bbox = img.getBoundingClientRect();
// the ratio by which our image has been scaled by CSS
var scale_x = img_bbox.width / img.naturalWidth;
var scale_y = img_bbox.height / img.naturalHeight;
// ...then
ctx.drawImage(img,
rect.left / scale_x,
rect.top / scale_y,
rect.width/ scale_x,
rect.height / scale_y,
0,
0,
rect.width,
rect.height
);
现在,您还必须考虑矩形位置和位置之间的差异,因此x
实际上就是(rect_bbox.left - img_bbox.left) / scale_x
。
您还没有清除的一件事是,如果您想在边界内或边界外进行裁切,即边界本身是否应为裁切区域的一部分。
这是一个也包含边框区域的示例。
onload = crop;
function crop() {
// get the rendered bounding box of our elements
var r_bbox = rect.getBoundingClientRect();
var img_bbox = img.getBoundingClientRect();
// the ratio by which our image has been scaled by CSS
var scale_x = img_bbox.width / img.naturalWidth;
var scale_y = img_bbox.height / img.naturalHeight;
// our output coords
var output = {
x: r_bbox.left - img_bbox.left,
y: r_bbox.top - img_bbox.top,
w: r_bbox.width,
h: r_bbox.height
};
var ctx = canvas.getContext('2d');
canvas.width = output.w;
canvas.height = output.h;
ctx.drawImage(img,
// source
// we need to scale all coords by the CSS scaling
output.x / scale_x,
output.y / scale_y,
output.w / scale_x,
output.h / scale_y,
// destination, to rendered space, no scaling
0,
0,
output.w,
output.h
);
}
img{
width: 200px;
height: 200px;
}
#rect{
position:absolute;
left: 42px;
top: 50px;
width: 100px;
height: 50px;
z-index: 2;
border: 5px solid rgba(0,255,0,.5);
}
*{
vertical-align: top;
}
<img id="img" src="https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg">
<div id="rect"></div>
<canvas id="canvas"></canvas>
只有边界区域内的东西
onload = crop;
function crop() {
// get the rendered bounding box of our elements
var r_bbox = rect.getBoundingClientRect();
var img_bbox = img.getBoundingClientRect();
// the ratio by which our image has been scaled by CSS
var scale_x = img_bbox.width / img.naturalWidth;
var scale_y = img_bbox.height / img.naturalHeight;
// our output coords
var output = {
// rect.clientLeft is the size of the left border
// so add it to 'x'
x: r_bbox.left - img_bbox.left + rect.clientLeft,
// same as for 'x'
y: r_bbox.top - img_bbox.top + rect.clientTop,
// size of padding box
w: rect.clientWidth,
h: rect.clientHeight
};
var ctx = canvas.getContext('2d');
canvas.width = output.w;
canvas.height = output.h;
ctx.drawImage(img,
output.x / scale_x,
output.y / scale_y,
output.w / scale_x,
output.h / scale_y,
0,
0,
output.w,
output.h
);
}
/* scale our image through CSS */
img{
width: 200px;
height: 200px;
}
#rect{
position:absolute;
left: 42px;
top: 50px;
width: 100px;
height: 50px;
z-index: 2;
border: 5px solid rgba(255,0,0,.5);
background: rgba(0,255,0,.5);
}
*{
vertical-align: top;
}
<img id="img" src="https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg">
<div id="rect"></div>
<canvas id="canvas"></canvas>