Skip to content

Instantly share code, notes, and snippets.

@ivnsch
Created December 26, 2016 21:43
Show Gist options
  • Save ivnsch/52eb0f3fb38e7274fd89a6db67bb08ed to your computer and use it in GitHub Desktop.
Save ivnsch/52eb0f3fb38e7274fd89a6db67bb08ed to your computer and use it in GitHub Desktop.
//: Playground 1: Simple setup, everything works.
import UIKit
import PlaygroundSupport
let domainPoint = CGPoint(x: 5, y: 5)
// The following variables are simplified ranges - all start with 0
let xDomain: CGFloat = 10
let yDomain: CGFloat = 10
let xScreenRange: CGFloat = 500
let yScreenRange: CGFloat = 500
func toScreenPoint(domainPoint: CGPoint) -> CGPoint {
return CGPoint(x: domainPoint.x * xScreenRange / xDomain, y: domainPoint.y * yScreenRange / yDomain)
}
func toDomain(screenPoint: CGPoint) -> CGPoint {
return CGPoint(x: screenPoint.x * xDomain / xScreenRange, y: screenPoint.y * yDomain / yScreenRange)
}
extension UIView {
// Changes the anchor of view without changing its position. Returns translation in pt
func setAnchorWithoutTranslation(anchor: CGPoint) -> CGPoint {
let offsetAnchor = CGPoint(x: anchor.x - layer.anchorPoint.x, y: anchor.y - layer.anchorPoint.y)
let offset = CGPoint(x: frame.width * offsetAnchor.x, y: frame.height * offsetAnchor.y)
layer.anchorPoint = anchor
transform = transform.translatedBy(x: offset.x, y: offset.y)
return offset
}
}
var screenPoint: CGPoint {
return toScreenPoint(domainPoint: domainPoint)
}
// The transform matrix to be applied to drawed lines in parent and to subview
var matrix = CGAffineTransform.identity
class MySuperview: UIView {
override func draw(_ rect: CGRect) {
let transformed: CGPoint = CGPoint(x: screenPoint.x, y: screenPoint.y).applying(matrix)
// Draw "cross" on superview
let path = UIBezierPath()
path.move(to: CGPoint(x: transformed.x, y: 0))
path.addLine(to: CGPoint(x: transformed.x, y: 1000))
path.close()
UIColor.black.set()
path.stroke()
let path2 = UIBezierPath()
path2.move(to: CGPoint(x: 0, y: transformed.y))
path2.addLine(to: CGPoint(x: 1000, y: transformed.y))
path2.close()
UIColor.black.set()
path2.stroke()
print("draw")
}
}
let root = UIView()
root.frame = CGRect(x: 0, y: 0, width: 600, height: 1000)
root.backgroundColor = UIColor.white
PlaygroundPage.current.liveView = root
let superview = MySuperview()
superview.frame = CGRect(x: 100, y: 100, width: xScreenRange, height: yScreenRange)
superview.backgroundColor = UIColor.orange.withAlphaComponent(0.3)
root.addSubview(superview)
let subview = UIView()
subview.frame = superview.bounds
subview.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
superview.addSubview(subview)
// Draw "cross" on subview (by adding subviews)
let contentLine = UIView()
contentLine.backgroundColor = UIColor.red.withAlphaComponent(0.4)
let contentLineWidth: CGFloat = 5
contentLine.frame = CGRect(x: screenPoint.x - contentLineWidth / 2, y: 0, width: contentLineWidth, height: 1000)
subview.addSubview(contentLine)
let contentLine2 = UIView()
contentLine2.backgroundColor = UIColor.red.withAlphaComponent(0.4)
contentLine2.frame = CGRect(x: 0, y: screenPoint.y - contentLineWidth / 2, width: 1000, height: contentLineWidth)
subview.addSubview(contentLine2)
// Set anchor point to (0, 0) to "sync" coordinate system with matrix
// Also, store the translation which has to preserve position while changing anchor, to use it to define subview's matrix in applyMatrixToSubview
let subviewAnchorTranslation = subview.setAnchorWithoutTranslation(anchor: CGPoint(x: 0, y: 0))
let newViewTransform = subview.transform
func zoom(center: CGPoint, level: CGPoint) {
matrix = matrix.translatedBy(x: center.x, y: center.y)
matrix.a = level.x
matrix.d = level.y
matrix = matrix.translatedBy(x: -center.x, y: -center.y)
superview.setNeedsDisplay()
print("subview trans before apply: \(subview.transform), matrix: \(matrix)")
applyMatrixToSubview()
print("subview trans after apply: \(subview.transform)")
}
func zoom(center: CGPoint, delta: CGPoint) {
zoom(center: center, level: CGPoint(x: matrix.a * delta.x, y: matrix.d * delta.y))
}
func applyMatrixToSubview() {
let m = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: subviewAnchorTranslation.x, ty: subviewAnchorTranslation.y)
subview.transform = matrix.concatenating(m)
}
func translate(delta: CGPoint) {
matrix.tx = matrix.tx + delta.x
matrix.ty = matrix.ty + delta.y
applyMatrixToSubview()
}
zoom(center: screenPoint, delta: CGPoint(x: 2, y: 2))
zoom(center: screenPoint, delta: CGPoint(x: 1.2, y: 1.2))
translate(delta: CGPoint(x: 70, y: 70))
//zoom(center: screenPoint, delta: CGPoint(x: 2.1, y: 2))
zoom(center: CGPoint(x: 200, y: 200), delta: CGPoint(x: 2.1, y: 2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment