簡體   English   中英

NSSlider animation

[英]NSSlider animation

更改浮點值時如何創建 NSSlider animation。 我在嘗試:

[[mySlider animator] setFloatValue:-5];

但這不起作用..只需更改沒有 animation 的值。 所以也許有人知道該怎么做?

提前致謝。

好的 - 所以這並不像我希望的那么快和漂亮,但它確實有效。 您無法在滑塊旋鈕上實際使用動畫師和核心動畫 - 因為Core Animation僅適用於圖層,並且無法訪問滑塊圖層中的旋鈕值。

所以我們不得不采用手動設置滑塊值的動畫。 由於我們在Mac上執行此操作 - 您可以使用NSAnimation (在iOS上不可用)。

NSAnimation所做的很簡單 - 它提供了一個定時/插值機制,允許你進行動畫處理(而不是核心動畫,它也連接到視圖並處理它們的變化)。

要使用NSAnimation - 您最常將它子類化並覆蓋setCurrentProgress:並將您的邏輯放在那里。

以下是我實現這一點的方法 - 我創建了一個名為NSAnimationForSlider的新NSAnimation子類

NSAnimationForSlider.h:

@interface NSAnimationForSlider : NSAnimation  
{  
    NSSlider *delegateSlider;  
    float animateToValue;    
    double max;   
    double min;  
    float initValue;  
}  
@property (nonatomic, retain) NSSlider *delegateSlider;  
@property (nonatomic, assign) float animateToValue;    
@end  

NSAnimationForSlider.m:

#import "NSAnimationForSlider.h"

@implementation NSAnimationForSlider
@synthesize delegateSlider;
@synthesize animateToValue;

-(void)dealloc
{
    [delegateSlider release], delegateSlider = nil;
}

-(void)startAnimation
{
    //Setup initial values for every animation
    initValue = [delegateSlider floatValue];
    if (animateToValue >= initValue) {
        min = initValue;
        max = animateToValue;
    } else  {
        min = animateToValue;
        max = initValue;
    }

    [super startAnimation];
}


- (void)setCurrentProgress:(NSAnimationProgress)progress
{
    [super setCurrentProgress:progress];

    double newValue;
    if (animateToValue >= initValue) {
        newValue = min + (max - min) * progress;        
    } else  {
        newValue = max - (max - min) * progress;
    }

    [delegateSlider setDoubleValue:newValue];
}

@end

要使用它 - 您只需創建一個新的NSAnimationForSlider,將它作為委托給您的滑塊,在每個動畫之前設置它為animateToValue然后啟動動畫。

例如:

slider = [[NSSlider alloc] initWithFrame:NSMakeRect(50, 150, 400, 25)];
[slider setMaxValue:200];
[slider setMinValue:50];
[slider setDoubleValue:50];

[[window contentView] addSubview:slider];

NSAnimationForSlider *sliderAnimation = [[NSAnimationForSlider alloc] initWithDuration:2.0 animationCurve:NSAnimationEaseIn];
[sliderAnimation setAnimationBlockingMode:NSAnimationNonblocking];
[sliderAnimation setDelegateSlider:slider];
[sliderAnimation setAnimateToValue:150];

[sliderAnimation startAnimation];

你的方法有效,但有一些更簡單的東西。

可以使用動畫師代理,你只需要告訴它如何動畫它。 為此,您需要從NSAnimatablePropertyContainer協議實現defaultAnimationForKey:方法。


這是NSSlider的一個簡單子類,它執行此操作:

#import "NSAnimatableSlider.h"
#import <QuartzCore/QuartzCore.h>

@implementation NSAnimatableSlider

+ (id)defaultAnimationForKey:(NSString *)key
{
    if ([key isEqualToString:@"doubleValue"]) {
        return [CABasicAnimation animation];
    } else {
        return [super defaultAnimationForKey:key];
    }
}

@end

現在您只需使用動畫代理:

[self.slider.animator setDoubleValue:100.0];

確保鏈接QuartzCore框架。

這是IluTov answer的 Swift 版本,使用一些 animation 配置設置floatValue

override class func defaultAnimation(forKey key: NSAnimatablePropertyKey) -> Any? {
    if key == "floatValue" {
        let animation = CABasicAnimation()
        animation.timingFunction = .init(name: .easeInEaseOut)
        animation.duration = 0.2
        
        return animation
    } else {
        return super.defaultAnimation(forKey: key)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM