我有一个CALayer托管视图,我希望能够缩放,滚动并单击。如果我将其嵌入滚动视图,滚动工作正常,但缩放会导致内容飞到各处。如果我没有将它嵌入到滚动视图中,我可以使用CATransform3DMakeScale很好地进行缩放,但是我在平移时遇到问题,并且能够选择对象。
在我尝试用错误的选项解决之前,建议的方法是什么?
(如果你有任何类似的来源,我会非常感激看到它。)
答案 0 :(得分:9)
另请查看Optimizing Drawing and Scrolling on OS X WWDC 2013 video
CALayer
中嵌入了ScrollView
,因为ScrollView
不是核心动画层(ScrollView.wantsLayer = true
)。
Swift中的示例:
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var win: NSWindow!
func applicationDidFinishLaunching(aNotification: NSNotification) {
win = NSWindow(contentRect: NSRect(x: 200, y: 200, width: 500, height: 500),
styleMask: NSTitledWindowMask,
backing: NSBackingStoreType.Buffered,
defer: false)
win.makeKeyAndOrderFront(win)
let scrollView = NSScrollView()
scrollView.allowsMagnification = true
scrollView.hasHorizontalScroller = true
scrollView.hasVerticalScroller = true
scrollView.wantsLayer = true
scrollView.contentView = CenteredClipView()
scrollView.documentView = MyView()
scrollView.backgroundColor = NSColor.controlColor()
win.contentView = scrollView
}
}
class MyView: NSView {
var drawn = false
override func updateLayer() {
super.updateLayer()
if !drawn {
drawn = true
frame = (superview! as NSView).frame
var shape = CAShapeLayer()
let p = CGPathCreateMutable()
CGPathAddEllipseInRect(p, nil, frame)
CGPathMoveToPoint(p, nil, bounds.maxX, 0)
CGPathAddLineToPoint(p, nil, 0, bounds.maxY)
shape.path = p
shape.lineWidth = 5
shape.fillColor = NSColor.whiteColor().CGColor
shape.strokeColor = NSColor.selectedControlColor().CGColor
shape.lineDashPattern = [5, 5]
let ant = CABasicAnimation(keyPath: "lineDashPhase")
ant.fromValue = 0
ant.toValue = 1000000
ant.duration = 10000
ant.repeatCount = 10000
shape.addAnimation(ant, forKey: "lineDashPhase")
layer?.addSublayer(shape)
}
}
}
class CenteredClipView: NSClipView {
override func constrainBoundsRect(proposedBounds: NSRect) -> NSRect {
var rect = super.constrainBoundsRect(proposedBounds)
if let containerView = documentView? as? NSView {
if rect.size.width > containerView.frame.size.width {
rect.origin.x = (containerView.frame.width - rect.width ) / 2
}
if rect.size.height > containerView.frame.size.height {
rect.origin.y = (containerView.frame.height - rect.height ) / 2
}
}
return rect
}
}