拍照,用零碎的,简略

本文次要是讲,抉择区域的旋转

  • 照片的旋转,用仿射变换
  • 抉择区域的旋转,就是旋转坐标系中的点,有一个坐标变换

手机 UIKit 框架下, view 的坐标系原点,是 view 的左上角

旋转坐标系中的点,个别坐标系用核心,不便


拍照,略。开始旋转抉择区域

1, 摆放好

下面有两个视图,放照片的 UIImageView, 和照片上拖拽视图 sketch

布局没有采纳,束缚

因为旋转的时候,他们的 frame 变来变去,

间接手动计算 frame, 更加的直观

         if let img = image{            let s = img.size.size(in: measure.s)                    imgView.frame.size = s            imgView.center = measure.center            sketch.frame = imgView.frame            // 照片            view.addSubview(imgView)            // 照片上的,拖拽区域            view.addSubview(sketch)            // ...        }

零碎拍照,默认分辨率, 4 : 3

为了简化计算,这里 imageView 的高/宽 = 其 image 的高/宽

拍照的图片,很大,适合的放在指定的小区域中

extension CGSize{        func size(in std: CGSize) -> CGSize{                let hRatio = height / std.height        let wRatio = width / std.width                let reSolution = height / width                        let s: CGSize                if hRatio > wRatio{            //  图片更窄            s = CGSize(width: std.height / reSolution, height: std.height)        }        else{            //  图片更宽            s = CGSize(width: std.width, height: std.width * reSolution)        }        return s            }}

2, 旋转

从图 a 到图 b , 是一个右旋

  • 旋转抉择区域视图,为了简化计算,旋转抉择区域的 frame 与看到的图片贴合

替换抉择区域的宽和高,就是批改尺寸 size,

复原其原来的中心点 center , 就是更新其原点

  • 旋转抉择区域视图,上的四个拖拽点,

先在原来的坐标系中,旋转角度,

抉择区域视图的原点变了,四个拖拽点旋转角度后,还需一个平移的弥补

    // 记录以后的角度    var angle: CGFloat = 0    @objc func rightTurn(){        rotate(with: .rhs)    }                func rotate(with direction: RotateOpt) {                let sizeOld = sketch.frame.size        let originOld = sketch.frame.origin        let center = sketch.center          switch direction {        case .lhs:                        // 逆时针                        angle -= 1                                    sketch.defaultPoints.update(clockwize: false, by: sizeOld)        case .rhs:                        // 顺时针                        angle += 1            // 旋转四个点            sketch.defaultPoints.update(clockwize: true, by: sizeOld)                    }                        // 图片视图,间接仿射变换        imgView.transform = CGAffineTransform(rotationAngle: ImgSingleAngle.time * angle)                sketch.frame.size = CGSize(width: sizeOld.height, height: sizeOld.width)                      sketch.center = center        let originNew = sketch.frame.origin        // 再弥补四个点        sketch.defaultPoints.patch(vector: originNew - originOld)                        // 更新绘制        sketch.reloadData()            }

旋转点的坐标,通过角度的变动,计算

    // 拿 size, 去算中心点    mutating    func update(clockwize beC: Bool, by area: CGSize){        let lhsTop: CGPoint, rhsTop: CGPoint, rhsBottom: CGPoint, lhsBottom: CGPoint        let center = CGPoint(x: area.width / 2, y: area.height / 2 )        if beC{            lhsTop = clockwize(rightTurn: leftTop, forCoordinate: center)            // ...        }        else{            lhsTop = antiClockwize(leftTurn: leftTop, forCoordinate: center)            // ...        }        leftTop = lhsTop        // ...                   }        // 顺时针旋转    private      func clockwize(rightTurn target: CGPoint, forCoordinate origin: CGPoint) -> CGPoint {          let dx = target.x - origin.x          let dy = target.y - origin.y          let radius = sqrt(dx * dx + dy * dy)          let azimuth = atan2(dy, dx) // in radians          let x = origin.x - radius * sin(azimuth)          let y = origin.y + radius * cos(azimuth)          return CGPoint(x: x, y: y)      }

3, 旋转增强,为了更好的利用手机区域,图片竖着更大,横着稍小一些

图片视图,仿射变换,是旋转 rotate + 缩放 scale

抉择区域视图 sketch, 不能简略的替换宽和高,

稍麻烦了一些

抉择区域视图 sketch 的 frame, 中心点不变,他的 size 有两个抉择,切换就好了

在上一步的根底上,计算抉择区域视图 sketch 的四个坐标
  • 竖着的,转横着的,大变小,上一步的坐标,放大就行
  • 横着的,转竖着的,小变大,先放大,再用规范坐标 ( 竖着的尺寸,替换后 ),投入计算
func rotate(with direction: RotateOpt) {        guard let img = image else {            return        }                let imgRatio = img.size.height / img.size.width        let const = 4.0/3        print(imgRatio, const)                let sizeOld = sketch.frame.size        let originOld = sketch.frame.origin        let center = sketch.center        let bigS = img.size.size(in: measure.s)        let clockwize: Bool        switch direction {        case .lhs:                        // 逆时针                        angle -= 1            clockwize = false                                case .rhs:                        // 顺时针                        angle += 1            clockwize = true                        // 下一步,对 UI 的批改,影响上一步                    }                                var ratio: CGFloat = 1                let smallS = img.size.size(by: measure.horizontal)                var imgTransform = CGAffineTransform(rotationAngle: ImgSingleAngle.time * angle)        if Int(angle) % 2 == 1{            ratio = smallS.width / bigS.height            imgTransform = imgTransform.scaledBy(x: ratio, y: ratio)            sketch.frame.size = smallS                   }        else{            ratio = bigS.height / smallS.width            sketch.frame.size = bigS                    }             // 旋转四个拖拽的点之前,先复位                // 小的,变大的,的时候,须要操作        if Int(angle) % 2 == 0{                      sketch.defaultPoints.scale(r: ratio, forS: sizeOld)        }        // 旋转,和平移弥补之前,先化为标注的,也就是竖着的尺寸        sketch.defaultPoints.update(clockwize: clockwize, by: sizeOld)        imgView.transform = imgTransform                       sketch.center = center        let originNew = sketch.frame.origin        // 弥补,跟上一步一样        sketch.defaultPoints.patch(vector: originNew - originOld)                        //  四个拖拽的点, 属于失常规范的图片                // 横着摆放,大变小        if Int(angle) % 2 == 1{                    sketch.defaultPoints.scale(r: ratio, forS: sizeOld)        }                // 绘制        sketch.reloadData()            }

前文, 低仿扫描全能王的抉择区域性能

github repo