通过反复使用透明黑色进行绘制来淡化图形在Mojave中已停止工作

时间:2019-07-15 16:47:52

标签: macos core-graphics nsview

===编辑以添加有关我想要获得的效果的更多信息===

在一个旧的屏幕保护程序中,我正在绘制类似彗星的东西:一个明亮的物体,它留下了消失的轨迹。因此,在每一帧中,我首先使用透明黑色(alpha设置为.02或类似值)绘制整个屏幕,然后在新位置绘制对象。 (当然,实际上有许多“彗星”,大约50个。)

6或8年前,这在Mac上运行良好,但现在在Mojave中,尽管正在发生淡入淡出,但它会忽然闪烁,就像在每次drawRect调用之前将视图擦除为黑色一样。

我只是在更新我在2010年左右编写的旧屏幕保护程序,我非常喜欢它,并且它停止在Mojave中工作。当时,这种淡入淡出技术效果很好,但是显然已经发生了变化。我怀疑有关后备存储或分层的信息。我希望能对此有所了解,可以找到相关信息的指针,并提供有关最佳做法的建议,以达到类似目的。

(据记录,我是90年代活跃的Mac程序员-有人还记得开发杂志吗?但是现在很少编程,所以Cocoa和Objective C对我来说仍然是“新手”。)

该代码很简单。在我的视图的drawRect中,在绘制任何打算淡出的新内容之前,我只是做:


// Erase to black, but with much transparency, to fade out any previous drawing
[[NSColor colorWithDeviceRed: 0.0 green: 0.0 blue: 0.0 alpha: 0.02] set];
[NSBezierPath fillRect: [self bounds]];

再次,我确信从挖掘中可以发现这与视图和图层支持有关,但是我不确定修复此问题的最佳实践,我想了解自己在做什么。任何朝着正确方向的指针都值得赞赏。

更新:我发现this的问题和答案看起来很有希望。但是,创建我自己的屏幕外图像真的有必要吗?我希望我可以在某个地方设置布尔值...:-)

1 个答案:

答案 0 :(得分:0)

基于答案here,我重新编写了代码以绘制成NSBitmapImageRep,现在看来它工作正常。我的小型测试应用程序中的相关代码:

// In this test app, frame redraws are triggered by a timer
- (void)DrawNewFrame:(NSTimer *)timer
{
    // just call our offscreen drawing routine, which will draw and then call setNeedsDisplay
    [self drawOffscreen];
}

- (void)drawOffscreen {
    // Set up the NSBitmapImageRep if it isn't already
    NSBitmapImageRep *cmap = cachedDrawingRep;
    if (!cmap) {
        cmap = [self bitmapImageRepForCachingDisplayInRect:self.bounds];
        cachedDrawingRep = cmap;
    }

    // Get ready to draw
    NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:cmap];
    [NSGraphicsContext saveGraphicsState];
    [NSGraphicsContext setCurrentContext:ctx];

    // Erase to black, but with much transparency, to fade out any previous drawing
    [[NSColor colorWithDeviceRed: 0.0 green: 0.0 blue: 0.0 alpha: 0.02] set];
    [NSBezierPath fillRect: [self bounds]];

    // Draw a little text if a key is tapped, to see it fade
    if( drawText )
    {
        // Make the font dictionary
        NSDictionary    *fontDict = [NSDictionary dictionaryWithObjectsAndKeys:
                    [NSFont fontWithName:@"Helvetica" size:12], NSFontAttributeName,
                    [NSColor redColor], NSForegroundColorAttributeName,
                    nil];

        NSString *helpStr = @"Fade This String!";
        [helpStr drawAtPoint:NSMakePoint(random() % 200, random() % 200) withAttributes: fontDict];
        drawText = NO;
    }
    [NSGraphicsContext restoreGraphicsState];

    // Make sure drawRect will get called
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect {
    if (cachedDrawingRep) {
        [cachedDrawingRep drawInRect:self.bounds];
    }
}

它现在完全按预期工作,所以我很高兴。谢谢!