我需要根据特定的纵横比(正方形、4x3、5x7、8x10 等)绘制一个选择矩形,以便裁剪图像。我有一些非常普通的代码可以处理在 touchesBegan/Moved 内自由拖动矩形的 4 个角,但我花了很长时间让它限制在特定的纵横比而不爬行或不准确。
这是我目前拥有的一些伪代码:
// this assumes that the four hitPoints are already arranged in the desired aspect ratio
CGPoint hitPoints[4]; // arranged botLeft=0, botRight=1, topRight=2, topLeft=3
CGPoint lastPoint;
CGRect cropRect;
int activeHitPoint;
#define kMinCropSize 20
- (void) touchesBegan
{
lastPoint = [touches locationInView:self];
activeHitPoint = [self getWhichPointTouched];
}
- (void) touchesMoved
{
CGPoint thisPoint = [touches locationInView:self];
float xDiff = thisPoint.x - lastPoint.x;
float yDiff = thisPoint.y - lastPoint.y;
float constrain = [self getAspectRatio]; // e.g.. 8x10 = 8/10 = 0.8
if(ABS(xDiff) > ABS(yDiff)){
yDiff = xDiff * constrain;
if(activeHitPoint == 1 || activeHitPoint == 3)
yDiff *= -1;
}else {
xDiff = yDiff * constrain;
if(activeHitPoint == 1 || activeHitPoint == 3)
xDiff *= -1;
}
switch(activeHitPoint){
case 0:
if((hitPoints[0].x + xDiff > imageDisplayRect.origin.x) &&
(hitPoints[0].x + xDiff + kMinCropSize < hitPoints[1].x) &&
(hitPoints[0].y + yDiff > imageDisplayRect.origin.y) &&
(hitPoints[0].y + yDiff + kMinCropSize < hitPoints[2].y)){
hitPoints[0].x += xDiff;
hitPoints[0].y += yDiff;
hitPoints[3].x = hitPoints[0].x;
hitPoints[1].y = hitPoints[0].y;
}
break;
case 1:
if((hitPoints[1].x + xDiff < imageDisplayRect.origin.x + imageDisplayRect.size.width) &&
(hitPoints[1].x + xDiff - kMinCropSize > hitPoints[0].x) &&
(hitPoints[1].y + yDiff > imageDisplayRect.origin.y) &&
(hitPoints[1].y + yDiff + kMinCropSize < hitPoints[2].y)){
hitPoints[1].x += xDiff;
hitPoints[1].y += yDiff;
hitPoints[2].x = hitPoints[1].x;
hitPoints[0].y = hitPoints[1].y;
}
break;
case 2:
if((hitPoints[2].x + xDiff < imageDisplayRect.origin.x + imageDisplayRect.size.width) &&
(hitPoints[2].x + xDiff - kMinCropSize > hitPoints[0].x) &&
(hitPoints[2].y + yDiff < imageDisplayRect.origin.y + imageDisplayRect.size.height) &&
(hitPoints[2].y + yDiff - kMinCropSize > hitPoints[1].y)){
hitPoints[2].x += xDiff;
hitPoints[2].y += yDiff;
hitPoints[1].x = hitPoints[2].x;
hitPoints[3].y = hitPoints[2].y;
}
break;
case 3:
if((hitPoints[3].x + xDiff > imageDisplayRect.origin.x) &&
(hitPoints[3].x + xDiff + kMinCropSize < hitPoints[2].x) &&
(hitPoints[3].y + yDiff < imageDisplayRect.origin.y + imageDisplayRect.size.height) &&
(hitPoints[3].y + yDiff - kMinCropSize > hitPoints[0].y)){
hitPoints[3].x += xDiff;
hitPoints[3].y += yDiff;
hitPoints[0].x = hitPoints[3].x;
hitPoints[2].y = hitPoints[3].y;
}
break;
}
cropRect = CGRectMake(hitPoints[0].x, hitPoints[0].y, hitPoints[1].x - hitPoints[0].x, hitPoints[2].y - hitPoints[1].y);
lastTouch = thisTouch;
[self setNeedsDisplay];
}
这段代码几乎可以工作,但它不是很准确......好像有舍入错误。随着时间的流逝,它会失去适当的纵横比,这令人惊讶……以及为什么我使用浮点数……但这似乎并不重要。