需求:汽车车体扫描动画,扫描结束显示另一种颜色的遮罩,期望结果如下
dongtu.gif
这里有两个知识点:
一是利用约束来做扫描动画
二是在4s和plus的机型上扫描图层和车体图层不能很好的重合(虽然两者的frame都是一致的),显示异常情况如下:
dongtu.gif
为方便行文,对几个图层进行命名:
车体的图层我们称之为CarView,
扫描的图层为ScanView
扫描时横线为LineView
图片:
有@2x和@3x两种图片
注:图片的大小是按屏幕宽按比例适配的
关于第一点:
将ScanView的contentMode设为UIViewContentModeTop,
clipsToBounds 设为 YES,通过定时器,每隔一段时间去更新ScanView的height,将LineView始终挨着ScanView的底部,当ScanView的高度变化,LineView的纵坐标也会随之变化,从而有了很好的扫描效果。代码如下(默认有一定编程童鞋看了,视图的初始化什么的就展示了):
初始约束 [self.scanView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.left.right.equalTo(ws.carView); make.height.mas_equalTo(@(0.f)); }]; [self.lineView mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(ws.scanView.mas_bottom).offset(6); make.left.right.equalTo(ws); make.size.mas_equalTo(CGSizeMake(kScreenWidth, 15)); }];
动画部分 - (void)startScanAnimation { self.scanView.hidden = NO; UIImage *image = [UIImage imageNamed:@"check_bg_scan"]; self.scanView.image = [self resizeImage:image NewHeight:kCarHeight]; self.lineView.hidden = NO; [self stepAnimation]; } - (void)stepAnimation { self.timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(scanCarAnimation) userInfo:nil repeats:YES]; NSRunLoop *main = [NSRunLoop currentRunLoop]; [main addTimer:self.timer forMode:NSRunLoopCommonModes]; } - (void)scanCarAnimation { WS(ws); CGFloat carHeight = kCarHeight; CGFloat perHeight = carHeight/100; __block CGFloat maskHeight = self.scanView.height; [ws.scanView mas_updateConstraints:^(MASConstraintMaker *make) { maskHeight += perHeight; if (maskHeight > carHeight) { maskHeight = 0; } make.height.mas_equalTo(@(maskHeight)); }]; [self layoutIfNeeded]; }
动画结束 - (void)showScanResult:(BOOL)isNormal { [self stopScanAnimation]; self.lineView.hidden = YES; self.scanView.hidden = NO; NSString *imgName = isNormal ? @"check_bg_success" : @"check_bg_error"; UIImage *image = [UIImage imageNamed:imgName]; self.scanView.image = [self resizeImage:image NewHeight:kCarHeight]; [self.scanView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(@(kCarHeight)); }]; } - (void)stopScanAnimation { if (_timer != nil && [_timer isValid]) { [_timer invalidate]; _timer = nil; } }
关于第二点:
排查下来,原因是做动画的图层的ScanView的contentMode设为UIViewContentModeTop, CarView的contentMode则是默认的, 在4s上ScanView的图片相较于CarView变大了,在plus上ScanView的图片相较于CarView却变小了。
由于图片的大小是随屏幕的宽按比例放大缩小的,所以在4s上图片的宽高都同步缩小了,图片相应的是被压缩了,而图片的contentMode是Top,并不能根据目标frame去自适应,所以ScanView自然就相对于已经自适应的CarView就显得大了。(plus上同理,至于Xr、Xs、Xs Max上没有这种情况,也许是系统做了某种处理)
解决办法就是将Image进行重绘成目标frame大小,这样即便contentMode是Top,对图片进行裁剪,和CarView可以很好的重合。
重绘图片的代码如下:
- (UIImage *)resizeImage:(UIImage *)originImage NewHeight:(CGFloat)newHeight { CGFloat scale = newHeight / originImage.size.height; CGFloat newWidth = originImage.size.width * scale; CGSize newSize = CGSizeMake(newWidth, newHeight); UIGraphicsBeginImageContext(newSize); [originImage drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }
作者:十六月
链接:https://www.jianshu.com/p/cb5f25a89c65
共同學習,寫下你的評論
評論加載中...
作者其他優質文章