为什么是空的drawRect用一个简单的动画干扰? [英] Why is an empty drawRect interfering with a simple animation?

查看:272
本文介绍了为什么是空的drawRect用一个简单的动画干扰?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想好好把我拿可可的 NSPathControl

I'm trying to put together my own take on Cocoa's NSPathControl.

在这里输入的形象描述

在力图找出处理扩大合同动画,当你鼠标在控制一个组成部分,我组建了一个非常简单的示例应用程序,你得到的最好方式。起初事情进展顺利 - 鼠标移入或移出包含路径成分的观点和你使用以下code得到一个简单的动画:

In a bid to figure out the best way to handle the expand-contract animation that you get when you mouse over a component in the control, I put together a very simple sample app. Initially things were going well - mouse into or out of the view containing the path components and you'd get a simple animation using the following code:

// This code belongs to PathView (not PathComponentView)

override func mouseEntered(theEvent: NSEvent) {

    NSAnimationContext.runAnimationGroup({ (ctx) -> Void in
        self.animateToProportions([CGFloat](arrayLiteral: 0.05, 0.45, 0.45, 0.05))
    }, completionHandler: { () -> Void in
            //
    })
}

// Animating subviews

func animateToProportions(proportions: [CGFloat]) {

    let height = self.bounds.height
    let width = self.bounds.width

    var xOffset: CGFloat = 0
    for (i, proportion) in enumerate(proportions) {
        let subview = self.subviews[i] as! NSView
        let newFrame = CGRect(x: xOffset, y: 0, width: width * proportion, height: height)
        subview.animator().frame = newFrame
        xOffset = subview.frame.maxX
    }
}

作为控制的下一步发展,而不是使用的NSView 实例,我开始使用我的路径组件我自己的的NSView 子类:

As the next step in the control's development, instead of using NSView instances as my path components I started using my own NSView subclass:

class PathComponentView: NSView {

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)
    }
}

虽然本质上等同于的NSView ,当我在我的动画使用这个类,动画不再做什么它应该 - 我为子视图设置帧pretty多少忽略,整体效果是丑陋的。如果我注释掉的drawRect:方法我子类的事情恢复正常。任何人能解释这是怎么回事了?为什么的drawRect的presence:与动漫干扰

Although essentially identical to NSView, when I use this class in my animation, the animation no longer does what it's supposed to - the frames I set for the subviews are pretty much ignored, and the whole effect is ugly. If I comment out the drawRect: method of my subclass things return to normal. Can anyone explain what's going wrong? Why is the presence of drawRect: interfering with the animation?

我已经把示范项目我的GitHub的页面上。

I've put a demo project on my GitHub page.

推荐答案

您已经在这里打破一些规则,而当你打破了规则,行为变得不确定。

You've broken some rules here, and when you break the rules, behavior becomes undefined.

在一个层支持的观点,你不能直接修改层。请参阅 wantsLayer 文档(这是你如何指定它的层支持的):

In a layer backed view, you must not modify the layer directly. See the documentation for wantsLayer (which is how you specify that it's layer-backed):

在一个层支持的观点,被认为做任何绘图缓存在底层对象。这个缓存的内容就可以在较明确重绘浏览内容更高性能的方式进行操作。 AppKit的自动创建底层对象(使用makeBackingLayer法)和处理视图的内容的高速缓存。 如果该wantsUpdateLayer方法返回NO,你不应该直接与底层对象交互。相反,使用这个类的方法,使以观其层的任何变化。如果wantsUpdateLayer返回YES,这是可以接受的(和适当的)在视图的updateLayer方法来修改层。

In a layer-backed view, any drawing done by the view is cached to the underlying layer object. This cached content can then be manipulated in ways that are more performant than redrawing the view contents explicitly. AppKit automatically creates the underlying layer object (using the makeBackingLayer method) and handles the caching of the view’s content. If the wantsUpdateLayer method returns NO, you should not interact with the underlying layer object directly. Instead, use the methods of this class to make any changes to the view and its layer. If wantsUpdateLayer returns YES, it is acceptable (and appropriate) to modify the layer in the view’s updateLayer method.

您做这个调用:

subview.layer?.backgroundColor = color.CGColor

这是直接交互[和]与底层对象。你不能做到这一点。如果没有的drawRect ,AppKit的跳过试图重绘视图,只是使用的Core Animation动画那里的东西,它给你你所期望(你刚刚幸运那里。它不答应这将工作)。

That's "interact[ing] with the underlying layer object directly." You're not allowed to do that. When there's no drawRect, AppKit skips trying to redraw the view and just uses Core Animation to animate what's there, which gives you what you expect (you're just getting lucky there; it's not promised this will work).

但是当它看到你真正实施的drawRect (它知道你做了,但是它不知道里面有什么),那么它必须调用它来执行自定义绘制。这是你的责任,以确保的drawRect 填充矩形的每一个像素。你不能依靠背面层来为你做的(这只是一个缓存)。你画什么,所以你看到的是使用缓存的混合色的默认背景灰色。有没有承诺,所有像素的一次,我们已经走了这条路将被正确更新。

But when it sees you actually implemented drawRect (it knows you did, but it doesn't know what's inside), then it has to call it to perform custom drawing. It's your responsibility to make sure that drawRect fills in every pixel of the rectangle. You can't rely on the backing layer to do that for you (that's just a cache). You draw nothing, so what you're seeing is the default background gray intermixed with cached color. There's no promise that all of the pixels will be updated correctly once we've gone down this road.

如果你要处理的图层,你希望有一个层托管视图而不是层支持的观点。您可以通过使用自己的自定义更换层AppKit框架的缓存层做到这一点。

If you want to manipulate the layer, you want a "layer-hosting view" not a "layer-backed view." You can do that by replacing AppKit's cache layer with your own custom layer.

let subview = showMeTheProblem ? PathComponentView() : NSView()
addSubview(subview)
subview.layer = CALayer() // Use our layer, not AppKit's caching layer.
subview.layer?.backgroundColor = color.CGColor

虽然它可能是在这种情况下,不要紧,请记住,一个层支持的视图和一个层托管观点有不同的表现特征。在一个层支持的观点,AppKit的是缓存你的的drawRect 成果转化为它的缓存层,然后在那还算自动应用的动画(这允许现有的AppKit的code,这是的CALayer之前写来得到一些不错的选择,在性能方面的改进,而不改变了)。在一个层托管视图,该系统更像iOS的。你不会得到任何神奇的缓存。这里只是一个层,你可以用它的Core Animation。

While it probably doesn't matter in this case, keep in mind that a layer-backed view and a layer-hosting view have different performance characteristics. In a layer-backed view, AppKit is caching your drawRect results into its caching layer, and then applying animations on that fairly automatically (this allows existing AppKit code that was written before CALayer to get some nice opt-in performance improvements without changing much). In a layer-hosting view, the system is more like iOS. You don't get any magical caching. There's just a layer, and you can use Core Animation on it.

这篇关于为什么是空的drawRect用一个简单的动画干扰?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆