Searching here in SO and in GitHub I found the following Swift class which acts a magnifer to magnify a portion of the UIView
around a point where the user touches the screen. Here's the code I found:
//
// MagnifyingGlassView.swift
//
// Created by Roman Kyrylenko on 01/11/15.
// Copyright (c) 2015 pr0ctopus.com All rights reserved.
//
import UIKit
public class MagnifyingGlassView: UIView {
var viewToMagnify: UIView?
var scale: CGFloat = 2.0
var zoomedPoint:CGPoint?
var size: CGFloat = 200.0 {
didSet {
let c = center
frame = CGRectMake(c.x - size / 2, c.y - size / 2, size, size)
}
}
var outlineColor: UIColor? {
didSet {
layer.borderColor = outlineColor?.CGColor
}
}
var outlineWidth: CGFloat? {
didSet {
layer.borderWidth = outlineWidth ?? 0.0
}
}
var touchPoint: CGPoint = CGPointZero {
didSet {
self.center = touchPoint
}
}
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
commonInit()
}
/*required public override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}*/
public init() {
super.init(frame: CGRectMake(0, 0, size, size))
commonInit()
}
public override func drawRect(rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext()
else { return }
/------!!!------/
CGContextTranslateCTM(context, frame.size.width / 2, frame.size.height / 2)
CGContextScaleCTM(context, scale, scale)
CGContextTranslateCTM(context, -zoomedPoint!.x, -zoomedPoint!.y)
/------!!!------/
hidden = true
viewToMagnify?.layer.renderInContext(context)
/* color of axes */
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0)
/* line width of axes */
CGContextSetLineWidth(context, 0.5)
/* draw vertical axis inside magnifier */
CGContextMoveToPoint(context, self.zoomedPoint!.x , self.zoomedPoint!.y - (self.frame.size.height / 2))
CGContextAddLineToPoint(context, self.zoomedPoint!.x, self.zoomedPoint!.y + (self.frame.size.height / 2))
/* draw horizontal axis inside magnifier */
CGContextMoveToPoint(context, self.zoomedPoint!.x - (self.frame.size.width / 2), self.zoomedPoint!.y)
CGContextAddLineToPoint(context, self.zoomedPoint!.x + (self.frame.size.width / 2), self.zoomedPoint!.y)
CGContextStrokePath(context)
hidden = false
}
private func commonInit() {
layer.cornerRadius = frame.size.width / 2
self.outlineWidth = 2.0
self.outlineColor = UIColor.lightGrayColor()
self.size = 200.0
layer.masksToBounds = true
}
}
The lines I don't understand are the ones contained between the /------!!!------/
. I mean that I don't understand why those translations are required when the aim of the magnifier is just to magnify a zone around a point. Why does it need to translate twice? what do they mean?
Would anyone explain me exactly how that stuff works?
What I think I have understood up to now is that with the first translation we give the magnifier a new reference system of graphic coordinates whose origin is the center of magnifier and the length of the axes are half the height and half the width of the magnifier itself. Then we perform a scale operation to zoom twice that graphic context and finally, with another translation, we set again the origin of the reference system of graphic coordinates of the magnifier as the point where the user has just touched the screen. Is this right?