Ios 如何将CGRect的大小增加一定的百分比值?

Ios 如何将CGRect的大小增加一定的百分比值?,ios,objective-c,swift,cgrect,Ios,Objective C,Swift,Cgrect,如何将CGRect的大小增加一定的百分比值?我应该使用某种形式的CGRectInset来完成吗 例如: 假设我有一个CGRect:{10,10,110,110} 我想将其大小(保留相同的中心点)增加20%,以: {0,0,120,120}如果您愿意,可以使用CGRectInset: double pct = 0.2; CGRect newRect = CGRectInset(oldRect, -CGRectGetWidth(oldRect)*pct/2, -CGRectGetHeight(old

如何将CGRect的大小增加一定的百分比值?我应该使用某种形式的
CGRectInset
来完成吗

例如:

假设我有一个CGRect:
{10,10,110,110}

我想将其大小(保留相同的中心点)增加20%,以:


{0,0,120,120}

如果您愿意,可以使用
CGRectInset

double pct = 0.2;
CGRect newRect = CGRectInset(oldRect, -CGRectGetWidth(oldRect)*pct/2, -CGRectGetHeight(oldRect)*pct/2);
要减小尺寸,请卸下
-
s

旁注:比
{10,10,100,100}
大20%的
CGRect
{0,0,120,120}


编辑:如果目的是按面积增加,则可以这样做(即使对于非正方形的矩形):


当然,使用
CGRectInset
可以:

CGRect someRect = CGRectMake(10, 10, 100, 100);
someRect = CGRectInset(someRect, someRect.size.width * -0.2, someRect.size.height * -0.2);
迅速:

func increaseRect(rect: CGRect, byPercentage percentage: CGFloat) -> CGRect {
    let startWidth = CGRectGetWidth(rect)
    let startHeight = CGRectGetHeight(rect)
    let adjustmentWidth = (startWidth * percentage) / 2.0
    let adjustmentHeight = (startHeight * percentage) / 2.0
    return CGRectInset(rect, -adjustmentWidth, -adjustmentHeight)
}

let rect = CGRectMake(0, 0, 10, 10)
let adjusted = increaseRect(rect, byPercentage: 0.1)
// -0.5, -0.5, 11, 11
在ObjC中:

- (CGRect)increaseRect:(CGRect)rect byPercentage:(CGFloat)percentage
{
    CGFloat startWidth = CGRectGetWidth(rect);
    CGFloat startHeight = CGRectGetHeight(rect);
    CGFloat adjustmentWidth = (startWidth * percentage) / 2.0;
    CGFloat adjustmentHeight = (startHeight * percentage) / 2.0;
    return CGRectInset(rect, -adjustmentWidth, -adjustmentHeight);
}

CGRect rect = CGRectMake(0,0,10,10);
CGRect adjusted = [self increaseRect:rect byPercentage:0.1];
// -0.5, -0.5, 11, 11

使用Swift,可以保留中心点(相对于源矩形),并使用扩展增加/减少大小,如下所示:


请注意,这种方法也会改变矩形的x和y。

Swift 4扩展受以下几个答案的启发,简化了计算:

extension CGRect {
    func scaleLinear(amount: Double) -> CGRect {
        guard amount != 1.0, amount > 0.0 else { return self }
        let ratio = ((1.0 - amount) / 2.0).cgFloat
        return insetBy(dx: width * ratio, dy: height * ratio)
    }

    func scaleArea(amount: Double) -> CGRect {
        return scaleLinear(percent: sqrt(amount))
    }

    func scaleLinear(percent: Double) -> CGRect {
        return scaleLinear(amount: percent / 100)
    }

    func scaleArea(percent: Double) -> CGRect {
        return scaleArea(amount: percent / 100)
    }
}
用法很简单:

rect.scaleLinear(percent: 120.0)  OR (amount: 1.2)
rect.scaleArea(percent: 120.0)  OR (amount: 1.2)
如果您有兴趣尝试我的测试方法:

/// Testing
extension CGRect {
    var area: CGFloat { return width * height }
    var center: CGPoint { return CGPoint(x: origin.x + width/2, y: origin.y + height/2)
    }

    func compare(_ r: CGRect) {
        let centered = center.x == r.center.x && center.y == r.center.y
        print("linear = \(r.width / width), area = \(r.area / area) centered \(centered)")
    }

    static func ScaleTest() {
        let rect = CGRect(x: 17, y: 24, width: 200, height: 100)
        let percent = 122.6
        rect.compare(rect.scaleLinear(percent: percent))
        rect.compare(rect.scaleArea(percent: percent))
    }
}

我在Swift代码中使用CGRect>insetBy

这样,您的百分比值将是
scaleX
,如我的示例所示

    let dx = rectWidth*scaleX
    let dy = rectHeight*scaleX
    let rectangle = CGRect(x: rectX,
                           y: rectY,
                           width: rectWidth,
                           height: rectHeight).insetBy(dx: -dx, dy: -dy)
  • 使用正值缩小比例
  • 使用负值放大

问题被标记为Objective-C。最好用所需的语言给出答案。+1是迄今为止唯一遵守苹果声明的回答者“应用程序应避免直接读取和写入存储在CGRect数据结构中的数据。相反,请使用此处描述的函数来操作矩形并检索其特征。“-苹果的声明很愚蠢。我更新了我的答案,以符合它的任何方式/紧随其后,我实际上也喜欢这个答案,因为它同时包含了Objc和Swift;)再看看这个,输出矩形不是应该是-1,-1,11,11吗?关于旁注:我认为remus(110110)给出的面积比(100100)大20%是正确的。我想这取决于你对“大20%”的解释。按面积计算,得到的正方形有长度为
109.5445
的边,这不如假设他打算将边的大小增加20%那么漂亮。我的意思是增加边的大小,但你是对的,面积将是一个完全不同的计算,这是一个很好的答案。很好,我将两者都包括在内。:)之所以选择它作为答案,是因为2017年,^它是
插入的
这似乎不会相对于矩形的中心进行缩放,因此不会更改x、y原点。正如上面的注释所述,这不会保留矩形的中心点!CGRect扩展很方便,但此代码不能正常工作。应将newX和newY添加到原点(x,y)。设newX=x+(w-newW)/2
rect.scaleLinear(percent: 120.0)  OR (amount: 1.2)
rect.scaleArea(percent: 120.0)  OR (amount: 1.2)
/// Testing
extension CGRect {
    var area: CGFloat { return width * height }
    var center: CGPoint { return CGPoint(x: origin.x + width/2, y: origin.y + height/2)
    }

    func compare(_ r: CGRect) {
        let centered = center.x == r.center.x && center.y == r.center.y
        print("linear = \(r.width / width), area = \(r.area / area) centered \(centered)")
    }

    static func ScaleTest() {
        let rect = CGRect(x: 17, y: 24, width: 200, height: 100)
        let percent = 122.6
        rect.compare(rect.scaleLinear(percent: percent))
        rect.compare(rect.scaleArea(percent: percent))
    }
}
    let dx = rectWidth*scaleX
    let dy = rectHeight*scaleX
    let rectangle = CGRect(x: rectX,
                           y: rectY,
                           width: rectWidth,
                           height: rectHeight).insetBy(dx: -dx, dy: -dy)