POP的spring动画各个参数详解

效果

源码

https://github.com/YouXianMing/POPSpring

//
//  RangeValueView.h
//  POPSpring
//
//  Created by YouXianMing on 15/5/14.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RangeValueView : UIView

/**
 *  文本标签
 */
@property (nonatomic, strong)   NSString  *text;

/**
 *  一些值的设置
 */
@property (nonatomic)           CGFloat    minValue;
@property (nonatomic)           CGFloat    maxValue;
@property (nonatomic, readonly) CGFloat    currentValue;
@property (nonatomic)           CGFloat    defaultValue;

/**
 *  便利构造器创建出视图
 *
 *  @param frame        控件的尺寸
 *  @param name         控件名字
 *  @param minValue     最小值
 *  @param maxValue     最大值
 *  @param defaultValue 默认值
 *
 *  @return 视图对象
 */
+ (instancetype)rangeValueViewWithFrame:(CGRect)frame
                                   name:(NSString *)name
                               minValue:(CGFloat)minValue
                               maxValue:(CGFloat)maxValue
                           defaultValue:(CGFloat)defaultValue;

@end
//
//  RangeValueView.m
//  POPSpring
//
//  Created by YouXianMing on 15/5/14.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import "RangeValueView.h"

#define    SLIDER_WIDTH    [UIScreen mainScreen].bounds.size.width

@interface RangeValueView ()

@property (nonatomic)          CGFloat    currentValue;

@property (nonatomic, strong)  UILabel   *labelName;
@property (nonatomic, strong)  UILabel   *labelValue;
@property (nonatomic, strong)  UISlider  *slider;

@end

@implementation RangeValueView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self initViews];
    }

    return self;
}

- (void)initViews {

    CGRect frame   = self.frame;
    CGFloat width  = frame.size.width;

    // 标签
    self.labelName               = [[UILabel alloc] initWithFrame:CGRectMake(3, 0, 100, 20)];
    self.labelName.font          = [UIFont fontWithName:@"AppleSDGothicNeo-Regular" size:12.f];
    [self addSubview:self.labelName];

    self.labelValue               = [[UILabel alloc] initWithFrame:CGRectMake(width - 103, 0, 100, 20)];
    self.labelValue.font          = [UIFont fontWithName:@"AppleSDGothicNeo-Regular" size:12.f];
    self.labelValue.textAlignment = NSTextAlignmentRight;
    [self addSubview:self.labelValue];

    // Slider
    self.slider = [[UISlider alloc] initWithFrame:CGRectMake(2, 15, width - 4, 10)];
    [self addSubview:self.slider];
    self.slider.minimumTrackTintColor = [[UIColor blackColor] colorWithAlphaComponent:0.1f];
    self.slider.maximumTrackTintColor = [[UIColor grayColor] colorWithAlphaComponent:0.05f];
    [self.slider setThumbImage:[UIImage imageNamed:@"slider"]
                      forState:UIControlStateNormal];
    [self.slider setThumbImage:[UIImage imageNamed:@"slider"]
                      forState:UIControlStateHighlighted];

    [self.slider addTarget:self
                    action:@selector(sliderChanged:)
          forControlEvents:UIControlEventValueChanged];
}

- (void)sliderChanged:(UISlider *)slider {
    // 更新UI
    CGFloat value        = slider.value;
    NSString *string     = [NSString stringWithFormat:@"%.2f", value];
    self.labelValue.text = string;

    // 当前的value值
    _currentValue        = value;
}

+ (instancetype)rangeValueViewWithFrame:(CGRect)frame
                                   name:(NSString *)name
                               minValue:(CGFloat)minValue
                               maxValue:(CGFloat)maxValue
                           defaultValue:(CGFloat)defaultValue {

    CGFloat x      = frame.origin.x;
    CGFloat y      = frame.origin.y;
    CGFloat width  = frame.size.width;
    CGFloat height = 25;

    RangeValueView *range = [[RangeValueView alloc] initWithFrame:CGRectMake(x, y, width, height)];

    // 基本配置
    range.maxValue        = maxValue;
    range.minValue        = minValue;
    range.defaultValue    = defaultValue;
    range.text            = name;

    // 额外配置
    range.currentValue    = defaultValue;
    range.labelValue.text = [NSString stringWithFormat:@"%.2f", defaultValue];

    return range;
}

@synthesize minValue = _minValue;
- (void)setMinValue:(CGFloat)minValue {
    _minValue            = minValue;
    _slider.minimumValue = minValue;
}
- (CGFloat)minValue {
    return _minValue;
}

@synthesize maxValue = _maxValue;
- (void)setMaxValue:(CGFloat)maxValue {
    _maxValue            = maxValue;
    _slider.maximumValue = maxValue;
}
- (CGFloat)maxValue {
    return _maxValue;
}

@synthesize defaultValue = _defaultValue;
- (void)setDefaultValue:(CGFloat)defaultValue {
    _defaultValue = defaultValue;
    _slider.value = defaultValue;
}
- (CGFloat)defaultValue {
    return _defaultValue;
}

@synthesize text = _text;
- (void)setText:(NSString *)text {
    _text           = text;
    _labelName.text = text;
}

- (NSString *)text {
    return _text;
}

@end
//
//  ViewController.m
//  POPSpring
//
//  Created by YouXianMing on 15/5/14.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "RangeValueView.h"
#import "POP.h"
#import "NSString+RichText.h"

@interface ViewController ()

@property (nonatomic, strong) UILabel  *secondsLabel;

@property (nonatomic, strong) UIButton *showView;
@property (nonatomic, strong) NSDate   *dateStart;

@property (nonatomic, strong) RangeValueView *rangeSpeed;
@property (nonatomic, strong) RangeValueView *rangeBounciness;
@property (nonatomic, strong) RangeValueView *rangeMass;
@property (nonatomic, strong) RangeValueView *rangeFriction;
@property (nonatomic, strong) RangeValueView *rangeTension;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self initSecondLabel];

    [self initButton];

    [self initRangeViews];
}

/**
 *  初始化显示秒钟的label
 */
- (void)initSecondLabel {
    self.secondsLabel                = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 20)];
    self.secondsLabel.attributedText = [self stringWithFloat:0.f];
    [self.view addSubview:self.secondsLabel];
}

/**
 *  创建富文本
 *
 *  @param value 输入的值
 *
 *  @return 返回创建好的富文本
 */
- (NSAttributedString *)stringWithFloat:(CGFloat)value {

    // 字符串
    NSString *stringValue  = [NSString stringWithFormat:@"%.2f", value];
    NSString *secondString = [NSString stringWithFormat:@"seconds"];
    NSString *totalString  = [NSString stringWithFormat:@"%@ %@", stringValue, secondString];

    // 字体
    UIFont *allFont        = [UIFont fontWithName:@"Avenir-Roman" size:14.f];
    UIFont *ValueFont      = [UIFont fontWithName:@"Avenir-Roman" size:16.f];

    // 配置富文本
    return [totalString createAttributedStringAndConfig:            @[
              [ConfigAttributedString font:allFont   range:[totalString range]],
              [ConfigAttributedString font:ValueFont range:[stringValue rangeFrom:totalString]],
              [ConfigAttributedString foregroundColor:[[UIColor grayColor] colorWithAlphaComponent:0.4f]
                                                range:[secondString rangeFrom:totalString]]
              ]];
}

/**
 *  初始化测试动画用的按钮
 */
- (void)initButton {

    CGFloat width                    = 100.f;
    self.showView                    = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, width, width)];
    self.showView.center             = CGPointMake(self.view.middleX, 175);
    self.showView.backgroundColor    = [UIColor cyanColor];
    self.showView.layer.cornerRadius = self.showView.width / 2.f;
    [self.view addSubview:self.showView];
    [self.showView addTarget:self
                      action:@selector(doAnimation)
            forControlEvents:UIControlEventTouchUpInside];
}

/**
 *  测试用rangeView
 */
- (void)initRangeViews {
    self.rangeSpeed = [RangeValueView rangeValueViewWithFrame:CGRectMake(10, Height - 60, Width - 20, 0)
                                                         name:@"速度  Speed"
                                                     minValue:0.f
                                                     maxValue:20.f
                                                 defaultValue:12.f];
    [self.view addSubview:self.rangeSpeed];

    self.rangeBounciness = [RangeValueView rangeValueViewWithFrame:CGRectMake(10, Height - 60 - 40, Width - 20, 0)
                                                              name:@"弹力  Bounciness"
                                                          minValue:0.f
                                                          maxValue:20.f
                                                      defaultValue:4.f];
    [self.view addSubview:self.rangeBounciness];

    self.rangeMass = [RangeValueView rangeValueViewWithFrame:CGRectMake(10, Height - 60 - 40*2, Width - 20, 0)
                                                        name:@"质量  Mass"
                                                    minValue:0.1
                                                    maxValue:10.f
                                                defaultValue:1.f];
    [self.view addSubview:self.rangeMass];

    self.rangeFriction = [RangeValueView rangeValueViewWithFrame:CGRectMake(10, Height - 60 - 40*3, Width - 20, 0)
                                                            name:@"摩擦  Friction"
                                                        minValue:1
                                                        maxValue:50
                                                    defaultValue:30.486980];
    [self.view addSubview:self.rangeFriction];

    self.rangeTension = [RangeValueView rangeValueViewWithFrame:CGRectMake(10, Height - 60 - 40*4, Width - 20, 0)
                                                           name:@"拉力  Tension"
                                                       minValue:1
                                                       maxValue:1000
                                                   defaultValue:300];
    [self.view addSubview:self.rangeTension];
}

/**
 *  执行动画操作
 */
- (void)doAnimation {

    // 移除动画
    [self.showView.layer pop_removeAllAnimations];

    POPSpringAnimation *spring = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];

    // 设置代理
    spring.delegate            = self;

    // 动画起始值 + 动画结束值
    spring.fromValue           = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
    spring.toValue             = [NSValue valueWithCGSize:CGSizeMake(2.f, 2.f)];

    // 参数的设置
    spring.springSpeed         = self.rangeSpeed.currentValue;
    spring.springBounciness    = self.rangeBounciness.currentValue;
    spring.dynamicsMass        = self.rangeMass.currentValue;
    spring.dynamicsFriction    = self.rangeFriction.currentValue;
    spring.dynamicsTension     = self.rangeTension.currentValue;

    // 执行动画
    [self.showView.layer pop_addAnimation:spring forKey:nil];
}

#pragma mark - POP动画相关代理
- (void)pop_animationDidStart:(POPAnimation *)anim {
    self.dateStart = [NSDate date];
}

- (void)pop_animationDidApply:(POPAnimation *)anim {
    CGFloat seconds                  = -[self.dateStart timeIntervalSinceNow];
    self.secondsLabel.attributedText = [self stringWithFloat:seconds];
}

- (void)pop_animationDidStop:(POPAnimation *)anim finished:(BOOL)finished {
    CGFloat seconds                  = -[self.dateStart timeIntervalSinceNow];
    self.secondsLabel.attributedText = [self stringWithFloat:seconds];
}

@end

说明

1. POP动画中的Spring弹簧动画因为没办法计算出动画所需要的时间,所以,本人写了一个demo用以测试不同参数下的弹簧动画效果以及花费的时间.

2. 本人写了一个小控件RangeValueView,可以单独拿出来用,很方便.

细节

时间: 2024-10-02 20:13:52

POP的spring动画各个参数详解的相关文章

spring @Transactional注解参数详解

事物注解方式: @Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: @Transactional public class TestServiceBean implements TestService {} 当类中某些方法不需要事物时: @Transactional public class TestServiceBean implements TestService { private TestDao dao; public void setDao(Tes

spring中Bean的注入参数详解

字面值    一般指可用字符串表示的值,这些值可以通过<value>元素标签进行注入.在默认情况下,基本数据类型及其封装类.String等类型都可以采取字面值注入的方式,Spring容器在内部为字面值提供了编辑器,它可以将以字符串表示的字面值转换为内部变量的相应类型.    配置信息:    <bean id="car" class="com.luxl.domain.Car">        <property name="m

VLC命令行参数详解

VLC命令行参数详解 2012-11-29 14:00 6859人阅读 评论(0) 收藏 举报 Usage: vlc [options] [stream] ...You can specify multiple streams on the commandline. They will be enqueued in the playlist.The first item specified will be played first. Options-styles:  --option  A gl

Spring IOC源码详解之容器初始化

Spring IOC源码详解之容器初始化 上篇介绍了Spring IOC的大致体系类图,先来看一段简短的代码,使用IOC比较典型的代码 ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDe

jQuery datepicker参数 详解

DatePicker支持鼠标点选日期,同时还可以通过键盘控制选择: page up/down - 上一月.下一月 ctrl+page up/down - 上一年.下一年 ctrl+home - 当前月或最后一次打开的日期 ctrl+left/right - 上一天.下一天 ctrl+up/down - 上一周.下一周 enter - 确定选择日期 ctrl+end - 关闭并清除已选择的日期 escape - 关闭并取消选择 实用功能: $.datepicker.setDefaults( set

Spring中AOP实例详解

Spring中AOP实例详解 需要增强的服务 假如有以下service,他的功能很简单,打印输入的参数并返回参数. @Service public class SimpleService { public String getName(String name) { System.out.println(get name is: + name); return name; } } 定义切面和切点 @Component @Aspect public class L ogAspect { // 定义切

Unity之粒子特效参数详解——上

如需转载请保留本文链接. Unity版本号:5.5.0 参考书籍:<Unity5.x从入门到精通> 参考资料:Unity官方API 参考文章: 1.http://jingyan.baidu.com/article/380abd0a77c5041d90192c19.html 2.http://www.cnblogs.com/qinghuaideren/p/3597666.html?utm_source=tuicool&utm_medium=referral 目标:做出一个篝火效果,最终结

Spring IOC源码详解之容器依赖注入

Spring IOC源码详解之容器依赖注入 上一篇博客中介绍了IOC容器的初始化,通过源码分析大致了解了IOC容器初始化的一些知识,先简单回顾下上篇的内容 载入bean定义文件的过程,这个过程是通过BeanDefinitionReader来完成的,其中通过 loadBeanDefinition()来对定义文件进行解析和根据Spring定义的bean规则进行处理 - 事实上和Spring定义的bean规则相关的处理是在BeanDefinitionParserDelegate中完成的,完成这个处理需

JVM 参数详解

在一些规模稍大的应用中,Java虚拟机(JVM)的内存设置尤为重要,想在项目中取得好的效率,GC(垃圾回收)的设置是第一步. PermGen space:全称是Permanent Generation space.就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域Heap space:存放Instance.GC(Garbage Collection)应该不会对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可