123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- //
- // LBXScanView.swift
- // swiftScan
- //
- // Created by xialibing on 15/12/8.
- // Copyright © 2015年 xialibing. All rights reserved.
- //
- import UIKit
- open class LBXScanView: UIView
- {
- //扫码区域各种参数
- var viewStyle:LBXScanViewStyle = LBXScanViewStyle()
-
- //扫码区域
- var scanRetangleRect:CGRect = CGRect.zero
-
- //线条扫码动画封装
- var scanLineAnimation:LBXScanLineAnimation?
-
- //网格扫码动画封装
- var scanNetAnimation:LBXScanNetAnimation?
-
- //线条在中间位置,不移动
- var scanLineStill:UIImageView?
-
- //启动相机时 菊花等待
- var activityView:UIActivityIndicatorView?
-
- //启动相机中的提示文字
- var labelReadying:UILabel?
-
- //记录动画状态
- var isAnimationing:Bool = false
-
- /**
- 初始化扫描界面
- - parameter frame: 界面大小,一般为视频显示区域
- - parameter vstyle: 界面效果参数
-
- - returns: instancetype
- */
- public init(frame:CGRect, vstyle:LBXScanViewStyle )
- {
- viewStyle = vstyle
-
- switch (viewStyle.anmiationStyle)
- {
- case LBXScanViewAnimationStyle.LineMove:
- scanLineAnimation = LBXScanLineAnimation.instance()
- break
- case LBXScanViewAnimationStyle.NetGrid:
- scanNetAnimation = LBXScanNetAnimation.instance()
- break
- case LBXScanViewAnimationStyle.LineStill:
- scanLineStill = UIImageView()
- scanLineStill?.image = viewStyle.animationImage
- break
-
-
- default:
- break
- }
-
- var frameTmp = frame;
- frameTmp.origin = CGPoint.zero
-
- super.init(frame: frameTmp)
-
- backgroundColor = UIColor.clear
- }
-
- override init(frame: CGRect) {
-
- var frameTmp = frame;
- frameTmp.origin = CGPoint.zero
-
- super.init(frame: frameTmp)
-
- backgroundColor = UIColor.clear
- }
-
- required public init?(coder aDecoder: NSCoder)
- {
- self.init()
-
- }
-
- deinit
- {
- if (scanLineAnimation != nil)
- {
- scanLineAnimation!.stopStepAnimating()
- }
- if (scanNetAnimation != nil)
- {
- scanNetAnimation!.stopStepAnimating()
- }
-
-
- // print("LBXScanView deinit")
- }
-
-
- /**
- * 开始扫描动画
- */
- func startScanAnimation()
- {
- if isAnimationing
- {
- return
- }
-
- isAnimationing = true
-
- let cropRect:CGRect = getScanRectForAnimation()
-
- switch viewStyle.anmiationStyle
- {
- case LBXScanViewAnimationStyle.LineMove:
-
- // print(NSStringFromCGRect(cropRect))
-
- scanLineAnimation!.startAnimatingWithRect(animationRect: cropRect, parentView: self, image:viewStyle.animationImage )
- break
- case LBXScanViewAnimationStyle.NetGrid:
-
- scanNetAnimation!.startAnimatingWithRect(animationRect: cropRect, parentView: self, image:viewStyle.animationImage )
- break
- case LBXScanViewAnimationStyle.LineStill:
-
- let stillRect = CGRect(x: cropRect.origin.x+20,
- y: cropRect.origin.y + cropRect.size.height/2,
- width: cropRect.size.width-40,
- height: 2);
- self.scanLineStill?.frame = stillRect
-
- self.addSubview(scanLineStill!)
- self.scanLineStill?.isHidden = false
-
- break
-
- default: break
-
- }
- }
-
- /**
- * 开始扫描动画
- */
- func stopScanAnimation()
- {
- isAnimationing = false
-
- switch viewStyle.anmiationStyle
- {
- case LBXScanViewAnimationStyle.LineMove:
-
- scanLineAnimation?.stopStepAnimating()
- break
- case LBXScanViewAnimationStyle.NetGrid:
-
- scanNetAnimation?.stopStepAnimating()
- break
- case LBXScanViewAnimationStyle.LineStill:
- self.scanLineStill?.isHidden = true
-
- break
-
- default: break
-
- }
- }
-
-
- // Only override drawRect: if you perform custom drawing.
- // An empty implementation adversely affects performance during animation.
- override open func draw(_ rect: CGRect)
- {
- // Drawing code
- drawScanRect()
- }
-
- //MARK:----- 绘制扫码效果-----
- func drawScanRect()
- {
- let XRetangleLeft = viewStyle.xScanRetangleOffset
- var sizeRetangle = CGSize(width: self.frame.size.width - XRetangleLeft*2.0, height: self.frame.size.width - XRetangleLeft*2.0)
- if viewStyle.whRatio != 1.0
- {
- let w = sizeRetangle.width;
- var h:CGFloat = w / viewStyle.whRatio
-
- let hInt:Int = Int(h)
- h = CGFloat(hInt)
-
- sizeRetangle = CGSize(width: w, height: h)
- }
-
- //扫码区域Y轴最小坐标
- let YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - viewStyle.centerUpOffset
- let YMaxRetangle = YMinRetangle + sizeRetangle.height
- let XRetangleRight = self.frame.size.width - XRetangleLeft
-
-
- // print("frame:%@",NSStringFromCGRect(self.frame))
-
- let context = UIGraphicsGetCurrentContext()!
-
-
- //非扫码区域半透明
- //设置非识别区域颜色
- context.setFillColor(viewStyle.color_NotRecoginitonArea.cgColor)
- //填充矩形
- //扫码区域上面填充
- var rect = CGRect(x: 0, y: 0, width: self.frame.size.width, height: YMinRetangle)
- context.fill(rect)
-
-
- //扫码区域左边填充
- rect = CGRect(x: 0, y: YMinRetangle, width: XRetangleLeft, height: sizeRetangle.height)
- context.fill(rect)
-
- //扫码区域右边填充
- rect = CGRect(x: XRetangleRight, y: YMinRetangle, width: XRetangleLeft,height: sizeRetangle.height)
- context.fill(rect)
-
- //扫码区域下面填充
- rect = CGRect(x: 0, y: YMaxRetangle, width: self.frame.size.width,height: self.frame.size.height - YMaxRetangle)
- context.fill(rect)
- //执行绘画
- context.strokePath()
-
-
- if viewStyle.isNeedShowRetangle
- {
- //中间画矩形(正方形)
- context.setStrokeColor(viewStyle.colorRetangleLine.cgColor)
- context.setLineWidth(1);
-
- context.addRect(CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height))
-
- //CGContextMoveToPoint(context, XRetangleLeft, YMinRetangle);
- //CGContextAddLineToPoint(context, XRetangleLeft+sizeRetangle.width, YMinRetangle);
-
- context.strokePath()
-
- }
- scanRetangleRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height)
-
-
- //画矩形框4格外围相框角
-
- //相框角的宽度和高度
- let wAngle = viewStyle.photoframeAngleW;
- let hAngle = viewStyle.photoframeAngleH;
-
- //4个角的 线的宽度
- let linewidthAngle = viewStyle.photoframeLineW;// 经验参数:6和4
-
- //画扫码矩形以及周边半透明黑色坐标参数
- var diffAngle = linewidthAngle/3;
- diffAngle = linewidthAngle / 2; //框外面4个角,与框有缝隙
- diffAngle = linewidthAngle/2; //框4个角 在线上加4个角效果
- diffAngle = 0;//与矩形框重合
-
- switch viewStyle.photoframeAngleStyle
- {
- case LBXScanViewPhotoframeAngleStyle.Outer:
- diffAngle = linewidthAngle/3//框外面4个角,与框紧密联系在一起
-
- case LBXScanViewPhotoframeAngleStyle.On:
- diffAngle = 0
-
- case LBXScanViewPhotoframeAngleStyle.Inner:
- diffAngle = -viewStyle.photoframeLineW/2
- }
-
- context.setStrokeColor(viewStyle.colorAngle.cgColor);
- context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0);
-
- // Draw them with a 2.0 stroke width so they are a bit more visible.
- context.setLineWidth(linewidthAngle);
-
-
- //
- let leftX = XRetangleLeft - diffAngle
- let topY = YMinRetangle - diffAngle
- let rightX = XRetangleRight + diffAngle
- let bottomY = YMaxRetangle + diffAngle
-
- //左上角水平线
- context.move(to: CGPoint(x: leftX-linewidthAngle/2, y: topY))
- context.addLine(to: CGPoint(x: leftX + wAngle, y: topY))
-
- //左上角垂直线
- context.move(to: CGPoint(x: leftX, y: topY-linewidthAngle/2))
- context.addLine(to: CGPoint(x: leftX, y: topY+hAngle))
-
- //左下角水平线
- context.move(to: CGPoint(x: leftX-linewidthAngle/2, y: bottomY))
- context.addLine(to: CGPoint(x: leftX + wAngle, y: bottomY))
-
- //左下角垂直线
- context.move(to: CGPoint(x: leftX, y: bottomY+linewidthAngle/2))
- context.addLine(to: CGPoint(x: leftX, y: bottomY - hAngle))
- //右上角水平线
- context.move(to: CGPoint(x: rightX+linewidthAngle/2, y: topY))
- context.addLine(to: CGPoint(x: rightX - wAngle, y: topY))
-
- //右上角垂直线
- context.move(to: CGPoint(x: rightX, y: topY-linewidthAngle/2))
- context.addLine(to: CGPoint(x: rightX, y: topY + hAngle))
- // 右下角水平线
- context.move(to: CGPoint(x: rightX+linewidthAngle/2, y: bottomY))
- context.addLine(to: CGPoint(x: rightX - wAngle, y: bottomY))
-
- //右下角垂直线
- context.move(to: CGPoint(x: rightX, y: bottomY+linewidthAngle/2))
- context.addLine(to: CGPoint(x: rightX, y: bottomY - hAngle))
-
- context.strokePath()
- }
-
- func getScanRectForAnimation() -> CGRect
- {
- let XRetangleLeft = viewStyle.xScanRetangleOffset
- var sizeRetangle = CGSize(width: self.frame.size.width - XRetangleLeft*2, height: self.frame.size.width - XRetangleLeft*2)
-
- if viewStyle.whRatio != 1
- {
- let w = sizeRetangle.width
- var h = w / viewStyle.whRatio
-
-
- let hInt:Int = Int(h)
- h = CGFloat(hInt)
-
- sizeRetangle = CGSize(width: w, height: h)
- }
-
- //扫码区域Y轴最小坐标
- let YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - viewStyle.centerUpOffset
- //扫码区域坐标
- let cropRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height)
-
- return cropRect;
- }
- //根据矩形区域,获取识别区域
- static func getScanRectWithPreView(preView:UIView, style:LBXScanViewStyle) -> CGRect
- {
- let XRetangleLeft = style.xScanRetangleOffset;
- var sizeRetangle = CGSize(width: preView.frame.size.width - XRetangleLeft*2, height: preView.frame.size.width - XRetangleLeft*2)
-
- if style.whRatio != 1
- {
- let w = sizeRetangle.width
- var h = w / style.whRatio
-
- let hInt:Int = Int(h)
- h = CGFloat(hInt)
-
- sizeRetangle = CGSize(width: w, height: h)
- }
-
- //扫码区域Y轴最小坐标
- let YMinRetangle = preView.frame.size.height / 2.0 - sizeRetangle.height/2.0 - style.centerUpOffset
- //扫码区域坐标
- let cropRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height)
-
-
- //计算兴趣区域
- var rectOfInterest:CGRect
-
- //ref:http://www.cocoachina.com/ios/20141225/10763.html
- let size = preView.bounds.size;
- let p1 = size.height/size.width;
-
- let p2:CGFloat = 1920.0/1080.0 //使用了1080p的图像输出
- if p1 < p2 {
- let fixHeight = size.width * 1920.0 / 1080.0;
- let fixPadding = (fixHeight - size.height)/2;
- rectOfInterest = CGRect(x: (cropRect.origin.y + fixPadding)/fixHeight,
- y: cropRect.origin.x/size.width,
- width: cropRect.size.height/fixHeight,
- height: cropRect.size.width/size.width)
-
-
- } else {
- let fixWidth = size.height * 1080.0 / 1920.0;
- let fixPadding = (fixWidth - size.width)/2;
- rectOfInterest = CGRect(x: cropRect.origin.y/size.height,
- y: (cropRect.origin.x + fixPadding)/fixWidth,
- width: cropRect.size.height/size.height,
- height: cropRect.size.width/fixWidth)
- }
- return rectOfInterest
- }
-
- func getRetangeSize()->CGSize
- {
- let XRetangleLeft = viewStyle.xScanRetangleOffset
-
- var sizeRetangle = CGSize(width: self.frame.size.width - XRetangleLeft*2, height: self.frame.size.width - XRetangleLeft*2)
-
- let w = sizeRetangle.width;
- var h = w / viewStyle.whRatio;
-
-
- let hInt:Int = Int(h)
- h = CGFloat(hInt)
-
- sizeRetangle = CGSize(width: w, height: h)
-
- return sizeRetangle
- }
-
- func deviceStartReadying(readyStr:String)
- {
- let XRetangleLeft = viewStyle.xScanRetangleOffset
-
- let sizeRetangle = getRetangeSize()
-
- //扫码区域Y轴最小坐标
- let YMinRetangle = self.frame.size.height / 2.0 - sizeRetangle.height/2.0 - viewStyle.centerUpOffset
-
- //设备启动状态提示
- if (activityView == nil)
- {
- self.activityView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
-
- activityView?.center = CGPoint(x: XRetangleLeft + sizeRetangle.width/2 - 50, y: YMinRetangle + sizeRetangle.height/2)
- activityView?.style = UIActivityIndicatorView.Style.whiteLarge
-
- addSubview(activityView!)
-
-
- let labelReadyRect = CGRect(x: activityView!.frame.origin.x + activityView!.frame.size.width + 10, y: activityView!.frame.origin.y, width: 100, height: 30);
- //print("%@",NSStringFromCGRect(labelReadyRect))
- self.labelReadying = UILabel(frame: labelReadyRect)
- labelReadying?.text = readyStr
- labelReadying?.backgroundColor = UIColor.clear
- labelReadying?.textColor = UIColor.white
- labelReadying?.font = UIFont.systemFont(ofSize: 18.0)
- addSubview(labelReadying!)
- }
-
- addSubview(labelReadying!)
- activityView?.startAnimating()
-
- }
-
- func deviceStopReadying()
- {
- if activityView != nil
- {
- activityView?.stopAnimating()
- activityView?.removeFromSuperview()
- labelReadying?.removeFromSuperview()
-
- activityView = nil
- labelReadying = nil
-
- }
- }
- }
|