最近工作中需要做一个类似于苹果输入法中语音识别的动画,方便用户通过语音,去控制智能设备。考虑了两种方案
- 苹果自带输入法的声音动画
- 下面是我自己实现的两种动画的UI
方案1
采用CAReplicatorLayer
- 缺点:不能实时的根据声音的大小来调节动画的幅度,所以不能满足要求
利用CAReplicatorLayer实现
- 1、什么是CAReplicatorLayer?
- 一种可以复制自己子层的layer,并且复制出来的layer和原生子层有同样的属性,位置,形变,动画。
- 2、CAReplicatorLayer属性
- instanceCount: 子层总数(包括原生子层)
- instanceDelay: 复制子层动画延迟时长
- instanceTransform: 复制子层形变(不包括原生子层),每个复制子层都是相对上一个。
- instanceColor: 子层颜色,会和原生子层背景色冲突,因此二者选其一设置。
- instanceRedOffset、instanceGreenOffset、instanceBlueOffset、instanceAlphaOffset: 颜色通道偏移量,每个复制子层都是相对上一个的偏移量。
直接上代码
CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = CGRectMake(50, 50, 200, 100);
replicatorLayer.backgroundColor = [UIColor lightGrayColor].CGColor;
// 设置4个子层,3个复制层
replicatorLayer.instanceCount = 4;
// 设置复制子层的相对位置,每个x轴相差40
replicatorLayer.instanceTransform = CATransform3DMakeTranslation(30, 0, 0);
// 设置复制子层的延迟动画时长
replicatorLayer.instanceDelay = 0.1;
[self.view.layer addSublayer:replicatorLayer];
CALayer *layer = [CALayer layer];
layer.backgroundColor = [UIColor redColor].CGColor;
layer.bounds = CGRectMake(0, 0, 10, 80);
layer.position = CGPointMake(30, 50);
layer.cornerRadius = 7.5;
layer.masksToBounds = YES;
[replicatorLayer addSublayer:layer];
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.scale.y";
animation.toValue = @(0.1);
animation.autoreverses = YES;
animation.repeatCount = MAXFLOAT;
animation.duration = 0.3;
[layer addAnimation:animation forKey:nil];
方案2:
采用 CADisplayLink UIBezierPath CAShapeLayer
- 可以根据声音的大小实时的修改动画的幅度
- 关于知识点详细介绍,可以看我另外的一篇文章
- 我这边采用随机数来模拟声音大小变化
直接上代码:
#import "SpeedWaveShapeLayerView.h"
#define HEXCOLORA(rgbValue, a) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0 blue:((float)(rgbValue & 0xFF)) / 255.0 alpha:a]
#define HEXCOLOR(rgbValue) HEXCOLORA(rgbValue, 1.0)
@interface SpeedWaveShapeLayerView()
@property (nonatomic, strong) NSMutableArray *itemArray;
@property (nonatomic, strong) NSMutableArray *levelArray;
@property (nonatomic, assign) NSUInteger numberOfItems;
@end
@implementation SpeedWaveShapeLayerView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_numberOfItems = 9;
_levelArray = [NSMutableArray array];
_itemArray = [NSMutableArray array];
}
return self;
}
- (void)setItemLevelCallback:(void (^)())itemLevelCallback {
_itemLevelCallback = itemLevelCallback;
CADisplayLink *displaylink = [CADisplayLink displayLinkWithTarget:_itemLevelCallback selector:@selector(invoke)];
displaylink.frameInterval = 6;
[displaylink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
for (int i = 0; i < _numberOfItems; i++) {
CAShapeLayer *itemline = [CAShapeLayer layer];
itemline.lineCap = kCALineCapRound;
itemline.lineJoin = kCALineJoinRound;
itemline.fillColor = [[UIColor clearColor] CGColor];
[itemline setLineWidth:4];
if (i == 0 || i == 1 || i == _numberOfItems - 1 || i == _numberOfItems - 2) {
itemline.strokeColor = HEXCOLORA(0xff2600, 0.1).CGColor;
} else if (i == 2 || i == _numberOfItems - 3) {
itemline.strokeColor = HEXCOLORA(0xff2600, 0.4).CGColor;
} else {
itemline.strokeColor = HEXCOLORA(0xff2600, 1.0).CGColor;
}
[self.layer addSublayer:itemline];
[self.itemArray addObject:itemline];
[self.levelArray addObject:@(2)];
}
}
- (void)updateWare {
UIGraphicsBeginImageContext(self.frame.size);
float left = (self.frame.size.width - 10 * _numberOfItems) / 2.0;
for (int i = 0; i < _numberOfItems; i++) {
UIBezierPath *itemLinePath = [UIBezierPath bezierPath];
float y = [[self.levelArray objectAtIndex:i] intValue];
if (i == 0 || i == _numberOfItems - 1) {
y = y * 3 / 7.0;
} else if (i == 1 || i == _numberOfItems - 2) {
y = y * 2 / 7.0;
} else if (i == 2 || i == _numberOfItems - 3) {
y = y * 3 / 7.0;
} else if (i == 3 || i == _numberOfItems - 4) {
y = y * 4 / 7.0;
}
[itemLinePath moveToPoint:CGPointMake(left + 10 * i, 30 + y)];
[itemLinePath addLineToPoint:CGPointMake(left + 10 * i, 30 - y)];
CAShapeLayer *shapeLayer = self.itemArray[i];
shapeLayer.path = [itemLinePath CGPath];
}
UIGraphicsEndImageContext();
}
- (void)setLevel:(NSInteger)level {
if (level < 3) {
level = 3;
}
_level = level;
[self.levelArray removeObjectAtIndex:self.numberOfItems - 1];
[self.levelArray insertObject:@(level) atIndex:0];
[self updateWare];
}
@end
常用的Layer子类
常用的Layer子类.png这里我主要用了 CAReplicationLayer 和 CAShapeLayer
网友评论