打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
iOS原生实现二维码拉近放大

关键时刻,第一时间送达!

Work Hard, Play Hard, Live Life.


前言


生活中,我们都是使用支付宝支付,当我们再扫描一个较远的二维码过程中,我们会发现,镜头会自动放大很容易扫到二维码进行支付。看起来这么人性化的操作,又是什么原理,该怎么实现呢?扫码现在很常见, 很多App基本都具备扫码功能, 网上也有很多对iOS二维码的讲解, Github上也有很多事例、开源的代码,但是发现APP扫码功能上,自动拉近扫描二维码的这波神操作,很少涉及。本文简单介绍如何iOS原生如何实现扫描较小二维码过程中拉近放大。

先看看本文效果图:


Demo效果图


对比支付宝扫码放大效果图:


支付宝


实现


从网络技术博客、Github上,我们都能很快实现一个二维码扫描功能,本文不再重复这些知识点。重点是如何拉近镜头和定位到二维码判断二维码大小。


iOS原生扫码


以下是iOS AVFoundation的扫码原理图。


原理图


拉近镜头


苹果提供了AVCaptureConnection中,videoScaleAndCropFactor:缩放裁剪系数,使用该属性,可以实现拉近拉远镜头。


  1. - (void)setVideoScale:(CGFloat)scale{ //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁 [_input.device lockForConfiguration:nil]; //获取放大最大倍数 AVCaptureConnection *videoConnection = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]]; CGFloat maxScaleAndCropFactor = ([[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor])/16; if (scale > maxScaleAndCropFactor)

  2.        scale = maxScaleAndCropFactor; CGFloat zoom = scale / videoConnection.videoScaleAndCropFactor;

  3.    videoConnection.videoScaleAndCropFactor = scale;

  4.    [_input.device unlockForConfiguration]; CGAffineTransform transform = _videoPreView.transform;

  5.    [CATransaction begin];

  6.    [CATransaction setAnimationDuration:.025];

  7.     _videoPreView.transform = CGAffineTransformScale(transform, zoom, zoom);

  8.    [CATransaction commit];

  9. }



实现步骤:


1、首先调用lockForConfiguration。

2、获取系统相机最大倍数,根据需求自定义MAX倍数。

3、改变videoScaleAndCropFactor。

4、unlockForConfiguration方法解锁。

5、将视图layer层放大对应的倍数。


1、注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁。

2、the videoScaleAndCropFactor property may be set to a value in the range of 1.0 to videoMaxScaleAndCropFactor,videoScaleAndCropFactor这个属性取值范围是1.0-videoMaxScaleAndCropFactor,如果你设置超出范围会崩溃哦




二维码定位


我们都知道,原生扫描结果AVCaptureMetadataOutputObjectsDelegate是返回了一个数组,而数组里面是一个个的AVMetadataMachineReadableCodeObject,而AVMetadataMachineReadableCodeObject中有个corners数组,记录二维码的坐标。查阅了官方文档和相关资料,我们很容易联想到,通过corners来获取二维码的坐标,大小形状。


@@property corners

@abstract The points defining the (X,Y)

locations of the corners of the machine-readable code.


@discussion

The value of this property is an NSArray of

NSDictionaries, each of which has been created from a CGPoint using

CGPointCreateDictionaryRepresentation(), representing the coordinates

of the corners of the object with respect to the image in which it

resides. If the metadata originates from video, the points may be

expressed as scalar values from 0. - 1. The points in the corners

differ from the bounds rectangle in that bounds is axis-aligned to

orientation of the captured image, and the values of the corners

reside within the bounds rectangle. The points are arranged in

counter-clockwise order (clockwise if the code or image is mirrored),

starting with the top-left of the code in its canonical orientation.


  1. #pragma mark AVCaptureMetadataOutputObjectsDelegate - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

  2. { if (!bNeedScanResult) { return;

  3.    }

  4.    bNeedScanResult = NO; if (!_arrayResult) { self.arrayResult = [NSMutableArray arrayWithCapacity:1];

  5.    } else {

  6.        [_arrayResult removeAllObjects];

  7.    } //识别扫码类型 for(AVMetadataObject *current in metadataObjects)

  8.    { if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] )

  9.        {

  10.            bNeedScanResult = NO; NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue]; if (scannedResult && ![scannedResult isEqualToString:@''])

  11.            {

  12.                [_arrayResult addObject:scannedResult];

  13.            } //测试可以同时识别多个二维码 }

  14.    } if (_arrayResult.count < 1)

  15.    {

  16.        bNeedScanResult = YES; return;

  17.    } if (_isAutoVideoZoom && !bHadAutoVideoZoom) { AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[self.preview transformedMetadataObjectForMetadataObject:metadataObjects.lastObject];

  18.        [self changeVideoScale:obj];

  19.         bNeedScanResult = YES;

  20.         bHadAutoVideoZoom  =YES; return;

  21.    } if (_isNeedCaputureImage)

  22.    {

  23.        [self captureImage];

  24.    } else {

  25.        [self stopScan]; if (_blockScanResult) {

  26.            _blockScanResult(_arrayResult);

  27.        }

  28.    }

  29. }



作者:程序鹅

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
IOS7使用原生API进行二维码和条形码的扫描
安装一个小插件 iPhone原生相机也能扫描二维码
ios js与oc原生WKWebView方法注入及交互传值
iOS objc
iOS8定位问题解决方案
使用HTML5构建iOS原生APP(2)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服