iOS 使用 CoreGraphics 在 canvas 内旋转图像

iOS rotate image inside canvas with CoreGraphics

我正在尝试旋转放置在矩形内且仅覆盖其中一部分的图像。

我找到了这个解决方案,但无法旋转图像:

override func drawRect(rect: CGRect) {
    let context = UIGraphicsGetCurrentContext()

    // drawing some texts and lines

    // rotate myImage by 'angle'
    CGContextSaveGState(context)

    CGContextTranslateCTM(context, imageOffset.x, imageOffset.y)
    CGContextRotateCTM(context, angle)
    CGContextTranslateCTM(context, -imageOffset.x, -imageOffset.y)
    myImage?.drawInRect(CGRect(x: imageOffset.x, y: imageOffset.y, width: imageSize.width, height: imageSize.height))

    CGContextRestoreGState(context)

    // draw other stuff
}

那么,如何正确地做呢?

您正在创建图像上下文,将图像绘制到其中,然后在不输出图像的情况下结束上下文。因此你永远不会看到输出。

您需要 UIGraphicsGetImageFromCurrentImageContext() 从上下文中取出旋转后的图像,然后在视图的上下文中重新绘制它。

像这样应该可以解决问题:

/// returns the transform equivalent of rotating a rect around its center
private func rotateTransformRectAroundCenter(rect:CGRect, angle:CGFloat) -> CGAffineTransform {
    let t = CGAffineTransformConcat(
        CGAffineTransformMakeTranslation(-rect.origin.x-rect.size.width*0.5, -rect.origin.y-rect.size.height*0.5),
        CGAffineTransformMakeRotation(angle)
    )
    return CGAffineTransformConcat(t, CGAffineTransformMakeTranslation(rect.size.width*0.5, rect.size.height*0.5))
}

override func drawRect(rect: CGRect) {

    // get current context
    let ctx = UIGraphicsGetCurrentContext()

    // the rect to draw the image in
    let rect = CGRect(x: 50, y: 50, width: 300, height: 300)

    // angle to rotate image by
    let angle = CGFloat(M_PI*0.25)

    // the image bounds
    let imgRect = CGRect(origin: CGPointZero, size: img.size)

    // transform of rotating image
    let imgRotate = rotateTransformRectAroundCenter(imgRect, angle: angle)

    // rotated image frame
    let rotatedImgFrame = CGRectApplyAffineTransform(imgRect, imgRotate)

    // transform of rotating image context
    let rotateContext = rotateTransformRectAroundCenter(rotatedImgFrame, angle: angle)


    // begin image context
    UIGraphicsBeginImageContextWithOptions(rotatedImgFrame.size, false, img.scale)

    let imgContext = UIGraphicsGetCurrentContext()

    // rotate image context
    CGContextConcatCTM(imgContext, rotateContext)

    // draw image in context
    img.drawInRect(CGRect(origin: CGPointZero, size: img.size))

    // get output from context
    let output = UIGraphicsGetImageFromCurrentImageContext()

    // end context
    UIGraphicsEndImageContext()

    // get the rotated rect for the image to be drawn in the main context
    var outputRect = CGRectApplyAffineTransform(rect, rotateTransformRectAroundCenter(rect, angle: angle))
    outputRect.origin = CGPoint(x: outputRect.origin.x+rect.origin.x, y: outputRect.origin.y+rect.origin.y)

    // draw image
    output.drawInRect(outputRect)
}