如何在绘制圆形以跟踪CALayer中的鼠标位置时克服滞后?

时间:2015-06-03 18:21:56

标签: swift drawing calayer nsview

我有一个支持图层的NSView。当鼠标进入视图时,我想在鼠标所在的任何地方绘制一个大圆圈。基本上跟踪鼠标位置。不幸的是,圆圈落后于实际的鼠标位置。

我认为它与隐式动画有关。禁用图层“content”属性的动画没有任何效果。

开始编辑:当鼠标移动而圆圈不在鼠标光标后面时,如何在鼠标光标位置绘制圆圈? :结束编辑

这是我的代码。

class TrackingView : NSView
{
override init(frame frameRect: NSRect)
{
    super.init(frame: frameRect)
    self.wantsLayer = true
}

required init?(coder: NSCoder)
{
    super.init(coder: coder)
    self.wantsLayer = true
}

//layer backing
override var wantsUpdateLayer : Bool { return true }

override func makeBackingLayer() -> CALayer
{
    return TrackingLayer()
}

//tracking areas
override func updateTrackingAreas()
{
    //remove current tracking area's
    while self.trackingAreas.count > 0
    {
        self.removeTrackingArea(self.trackingAreas.first as! NSTrackingArea)
    }

    if let trackingFrames = (self.layer as? TrackingLayer)?.trackingFrames
    {
        for trackingFrame in trackingFrames
        {
            let trackingArea = NSTrackingArea(
                rect: trackingFrame,
                options: NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInActiveApp | NSTrackingAreaOptions.MouseMoved,
                owner: self,
                userInfo: nil)
            self.addTrackingArea(trackingArea)
        }
    }
}

//mouse
override func mouseEntered(event: NSEvent)
{
    (self.layer as? TrackingLayer)?.userLocation = self.convertPoint(event.locationInWindow, fromView: nil)
}

override func mouseMoved(event: NSEvent)
{
    (self.layer as? TrackingLayer)?.userLocation = self.convertPoint(event.locationInWindow, fromView: nil)
}
}

class TrackingLayer : CALayer
{
var trackingFrames : [NSRect] { return [self.frame] }
var userLocation : CGPoint? {
    didSet { self.setNeedsDisplay() }
}

override init!()
{
    super.init()
    self.disableAnimations()
    self.backgroundColor = NSColor.whiteColor().CGColor
}
override init!(layer: AnyObject!)
{
    super.init(layer: layer)
    self.disableAnimations()
}

required init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder)
    self.disableAnimations()
}

//animations
private func disableAnimations()
{
    self.actions = [
        "content"   : NSNull(),
        "sublayers" : NSNull()]
}

//drawing
override func drawInContext(context: CGContext!)
{
    if var assumedUserLocation = userLocation
    {
        CGContextStrokeEllipseInRect(context, CGRectMake(assumedUserLocation.x-5, assumedUserLocation.y-5, 10, 10))
        CGContextFillEllipseInRect(context, CGRectMake(assumedUserLocation.x-5, assumedUserLocation.y-5, 10, 10))
    }
}
}

1 个答案:

答案 0 :(得分:0)

为要进行的更改禁用CALayers动画

CATransaction.withDisabledActions {
   hitLayer.move(by: dx, y: dy)
}


extension CATransaction {
    class func withDisabledActions<T>(_ body: () throws -> T) rethrows -> T {
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        defer {
            CATransaction.commit()
        }
        return try body()
    }
}

也请检查一下,因为这可能更简单

Drawing selection box (rubberbanding, marching ants) in Cocoa, ObjectiveC