国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

10.2 自定義緩沖函數(shù)

2018-02-24 15:07 更新

自定義緩沖函數(shù)

在第八章中,我們給時鐘項目添加了動畫??雌饋砗苜潱侨绻泻线m的緩沖函數(shù)就更好了。在顯示世界中,鐘表指針轉(zhuǎn)動的時候,通常起步很慢,然后迅速啪地一聲,最后緩沖到終點。但是標(biāo)準(zhǔn)的緩沖函數(shù)在這里每一個適合它,那該如何創(chuàng)建一個新的呢?

除了+functionWithName:之外,CAMediaTimingFunction同樣有另一個構(gòu)造函數(shù),一個有四個浮點參數(shù)的+functionWithControlPoints::::(注意這里奇怪的語法,并沒有包含具體每個參數(shù)的名稱,這在objective-C中是合法的,但是卻違反了蘋果對方法命名的指導(dǎo)方針,而且看起來是一個奇怪的設(shè)計)。

使用這個方法,我們可以創(chuàng)建一個自定義的緩沖函數(shù),來匹配我們的時鐘動畫,為了理解如何使用這個方法,我們要了解一些CAMediaTimingFunction是如何工作的。

三次貝塞爾曲線

CAMediaTimingFunction函數(shù)的主要原則在于它把輸入的時間轉(zhuǎn)換成起點和終點之間成比例的改變。我們可以用一個簡單的圖標(biāo)來解釋,橫軸代表時間,縱軸代表改變的量,于是線性的緩沖就是一條從起點開始的簡單的斜線(圖10.1)。

圖10.2 三次貝塞爾緩沖函數(shù)

實際上它是一個很奇怪的函數(shù),先加速,然后減速,最后快到達(dá)終點的時候又加速,那么標(biāo)準(zhǔn)的緩沖函數(shù)又該如何用圖像來表示呢?

CAMediaTimingFunction有一個叫做-getControlPointAtIndex:values:的方法,可以用來檢索曲線的點,這個方法的設(shè)計的確有點奇怪(或許也就只有蘋果能回答為什么不簡單返回一個CGPoint),但是使用它我們可以找到標(biāo)準(zhǔn)緩沖函數(shù)的點,然后用UIBezierPathCAShapeLayer來把它畫出來。

曲線的起始和終點始終是{0, 0}和{1, 1},于是我們只需要檢索曲線的第二個和第三個點(控制點)。具體代碼見清單10.4。所有的標(biāo)準(zhǔn)緩沖函數(shù)的圖像見圖10.3。

清單10.4 使用UIBezierPath繪制CAMediaTimingFunction

@interface ViewController ()

@property (nonatomic, weak) IBOutlet UIView *layerView;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //create timing function
    CAMediaTimingFunction *function = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut];
    //get control points
    CGPoint controlPoint1, controlPoint2;
    [function getControlPointAtIndex:1 values:(float *)&controlPoint1];
    [function getControlPointAtIndex:2 values:(float *)&controlPoint2];
    //create curve
    UIBezierPath *path = [[UIBezierPath alloc] init];
    [path moveToPoint:CGPointZero];
    [path addCurveToPoint:CGPointMake(1, 1)
            controlPoint1:controlPoint1 controlPoint2:controlPoint2];
    //scale the path up to a reasonable size for display
    [path applyTransform:CGAffineTransformMakeScale(200, 200)];
    //create shape layer
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.strokeColor = [UIColor redColor].CGColor;
    shapeLayer.fillColor = [UIColor clearColor].CGColor;
    shapeLayer.lineWidth = 4.0f;
    shapeLayer.path = path.CGPath;
    [self.layerView.layer addSublayer:shapeLayer];
    //flip geometry so that 0,0 is in the bottom-left
    self.layerView.layer.geometryFlipped = YES;
}

@end

圖10.4 自定義適合時鐘的緩沖函數(shù)

清單10.5 添加了自定義緩沖函數(shù)的時鐘程序

- (void)setAngle:(CGFloat)angle forHand:(UIView *)handView ?animated:(BOOL)animated
{
    //generate transform
    CATransform3D transform = CATransform3DMakeRotation(angle, 0, 0, 1);
    if (animated) {
        //create transform animation
        CABasicAnimation *animation = [CABasicAnimation animation];
        animation.keyPath = @"transform";
        animation.fromValue = [handView.layer.presentationLayer valueForKey:@"transform"];
        animation.toValue = [NSValue valueWithCATransform3D:transform];
        animation.duration = 0.5;
        animation.delegate = self;
        animation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:1 :0 :0.75 :1];
        //apply animation
        handView.layer.transform = transform;
        [handView.layer addAnimation:animation forKey:nil];
    } else {
        //set transform directly
        handView.layer.transform = transform;
    }
}

更加復(fù)雜的動畫曲線

考慮一個橡膠球掉落到堅硬的地面的場景,當(dāng)開始下落的時候,它會持續(xù)加速知道落到地面,然后經(jīng)過幾次反彈,最后停下來。如果用一張圖來說明,它會如圖10.5所示。

這可以起到作用,但效果并不是很好,到目前為止我們所完成的只是一個非常復(fù)雜的方式來使用線性緩沖復(fù)制CABasicAnimation的行為。這種方式的好處在于我們可以更加精確地控制緩沖,這也意味著我們可以應(yīng)用一個完全定制的緩沖函數(shù)。那么該如何做呢?

緩沖背后的數(shù)學(xué)并不很簡單,但是幸運的是我們不需要一一實現(xiàn)它。羅伯特·彭納有一個網(wǎng)頁關(guān)于緩沖函數(shù)(http://www.robertpenner.com/easing),包含了大多數(shù)普遍的緩沖函數(shù)的多種編程語言的實現(xiàn)的鏈接,包括C。這里是一個緩沖進(jìn)入緩沖退出函數(shù)的示例(實際上有很多不同的方式去實現(xiàn)它)。

float quadraticEaseInOut(float t) 
{
    return (t < 0.5)? (2 * t * t): (-2 * t * t) + (4 * t) - 1; 
}

對我們的彈性球來說,我們可以使用bounceEaseOut函數(shù):

float bounceEaseOut(float t)
{
    if (t < 4/11.0) {
        return (121 * t * t)/16.0;
    } else if (t < 8/11.0) {
        return (363/40.0 * t * t) - (99/10.0 * t) + 17/5.0;
    } else if (t < 9/10.0) {
        return (4356/361.0 * t * t) - (35442/1805.0 * t) + 16061/1805.0;
    }
    return (54/5.0 * t * t) - (513/25.0 * t) + 268/25.0;
}

如果修改清單10.7的代碼來引入bounceEaseOut方法,我們的任務(wù)就是僅僅交換緩沖函數(shù),現(xiàn)在就可以選擇任意的緩沖類型創(chuàng)建動畫了(見清單10.8)。

清單10.8 用關(guān)鍵幀實現(xiàn)自定義的緩沖函數(shù)

- (void)animate
{
    //reset ball to top of screen
    self.ballView.center = CGPointMake(150, 32);
    //set up animation parameters
    NSValue *fromValue = [NSValue valueWithCGPoint:CGPointMake(150, 32)];
    NSValue *toValue = [NSValue valueWithCGPoint:CGPointMake(150, 268)];
    CFTimeInterval duration = 1.0;
    //generate keyframes
    NSInteger numFrames = duration * 60;
    NSMutableArray *frames = [NSMutableArray array];
    for (int i = 0; i < numFrames; i++) {
        float time = 1/(float)numFrames * i;
        //apply easing
        time = bounceEaseOut(time);
        //add keyframe
        [frames addObject:[self interpolateFromValue:fromValue toValue:toValue time:time]];
    }
    //create keyframe animation
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    animation.duration = 1.0;
    animation.delegate = self;
    animation.values = frames;
    //apply animation
    [self.ballView.layer addAnimation:animation forKey:nil];
}
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號