使用NSScrollView进行CALayer,缩放平移和单击

时间:2014-12-12 11:00:18

标签: macos calayer nsview nsscrollview

我有一个CALayer托管视图,我希望能够缩放,滚动并单击。如果我将其嵌入滚动视图,滚动工作正常,但缩放会导致内容飞到各处。如果我没有将它嵌入到滚动视图中,我可以使用CATransform3DMakeScale很好地进行缩放,但是我在平移时遇到问题,并且能够选择对象。

在我尝试用错误的选项解决之前,建议的方法是什么?

(如果你有任何类似的来源,我会非常感激看到它。)

1 个答案:

答案 0 :(得分:9)

我在Apple sample codes

受到启发

另请查看Optimizing Drawing and Scrolling on OS X WWDC 2013 video

CALayer中嵌入了ScrollView,因为ScrollView不是核心动画层ScrollView.wantsLayer = true)。 Interface Builder

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
    }
}