이미지에서 확대 확대 부분 이동 애니메이션

이미지 분석에 사용할 응용 프로그램을 만들 때 분석 기간(통신에서) 활동 지시기만 표시하면 너무 간단하고 지루하다. 백엔드에서는 분석 후 결과를 다른 서비스와 연결시키기 때문에 응답이 번거로울 수 있다.
이벤트 표시기와 표시하고 사용하는 형식으로 사용자의 대기 시간을 살짝 속이는 이미지 해석에서 애니메이션이 쉽게 실현되었다.

해석 중의 표현


이미지 분석에서 UX는 어떤 표현일까요?
API 측이 어떤 논리로 분석됐는지 알 수 없고 그것만 고려할 수밖에 없다.
  • 이미지에 모자이크를 넣어 점점 사라지는 느낌
    →순환불가, NG
  • 이미지의 끝에서 끝까지 픽셀을 변조하는 느낌
    →순환불가, NG
  • 영화와 드라마에서 가로, 세로, 직사각형으로 이동하는 장면을 자주 본다.
    →싸진다
  • 그러고 보니 이 프로그램의 이미지 해석 기능 아이콘을 만들 때'이미지'와'확대경'을 주제로 그림그림을 만들었던 기억이 난다.해석을 진행하는 이미지에서 확대표시 원이 확대경처럼 무작위로 이동하면 해석의 느낌도 있고 디자인의 일치성도 있다.

    확대경 운동


    만약 완전히 무작위로 점이 이동하면 이미지의 가장자리만 이동하거나 같은 곳만 이동하는 것이 마치 분석에 핵심이 없는 것처럼 어느 정도 이미지의 한복판에 집중하여 두루 이동하지 않도록 하는 논리이다.
    그림의 중심에서 시작할 때 중심에 편향된 점을 정의하고 무작위 속도로 이동합니다.
    // Returns random point
    func randomPosition() -> CGPoint {
        let size = CGSize(width: magnificationImageRect.width, height: magnificationImageRect.height)
        let xPoints: [CGFloat] = [size.width * 0.2, size.width * 0.35, size.width * 0.45, size.width * 0.55, size.width * 0.65, size.width * 0.8]
        let yPoints: [CGFloat] = [size.height * 0.2, size.height * 0.35, size.height * 0.45, size.height * 0.55, size.height * 0.65, size.height * 0.8]
        let x = xPoints[Int(arc4random() % UInt32(xPoints.count))]
        let y = yPoints[Int(arc4random() % UInt32(yPoints.count))]
        return CGPoint(x: x, y: y)
    }
    
    또한 랜덤으로 발생하기 때문에 앞의 점과 같은 점을 사용하지 않는 논리를 넣었다.
    repeat {
        nextPosition = randomPosition()
    } while nextPosition == position
    
    통신 시간을 몰라 한 번에 끝나는 애니메이션은 안 되기 때문에 반복해서 재생할 수 없다.순환이 부자연스럽지 않아도 처음과 마지막은 같은 요점이다.
    // Back to initial position for loop
    let lastAnimation = appendAnimation(position: position, nextPosition: initialPosition, totalDuration: totalDuration)
    

    구조


    뷰 구조는 아래쪽에서 시작합니다.
  • 분석 대상 이미지 UIImageView
  • 래치 UIView
  • 확대된 분석 개체 이미지 UIImageView
  • 부분 확대경 CALayer
  • private let imageView = UIImageView()
    private let magnificationView = UIView()
    private let magnificationImageView = UIImageView()
    private let magnificationMaskLayer = CALayer()
    
    사이즈는 확대경 부분으로 확대된 이미지를 가리고 이동합니다.
    패키지는 원본 분석 대상의 이미지를 초과하지 않기 위해 내용을 편집합니다.
    override init(frame: CGRect) {
        super.init(frame: frame)
        imageView.image = UIImage(named: "cancun_pool_bar.png")
        addSubview(imageView)
    
        magnificationView.isHidden = true
        magnificationView.clipsToBounds = true
        addSubview(magnificationView)
    
        magnificationImageView.image = imageView.image
        magnificationView.addSubview(magnificationImageView)
    
        magnificationMaskLayer.backgroundColor = UIColor.black.cgColor
        magnificationMaskLayer.cornerRadius = 100
        magnificationMaskLayer.frame.size = CGSize(width: 200, height: 200)
        magnificationImageView.layer.mask = magnificationMaskLayer
    
        imageView.snp.makeConstraints { (make) in
            make.center.size.equalToSuperview()
        }
    
        magnificationView.snp.makeConstraints { (make) in
            make.center.size.equalTo(imageView)
        }
    
        magnificationImageView.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
            make.size.equalToSuperview().multipliedBy(2.0)
        }
    }
    
    정의된 점에서 랜덤으로 10개magnificationMaskLayer를 골라 추가CABasicAnimation한다.
    // Start from center
    var position: CGPoint = CGPoint(x: magnificationImageRect.width / 2, y: magnificationImageRect.height / 2)
    let initialPosition: CGPoint = position
    var totalDuration = 0.0
    for _ in 0...10 {
        var nextPosition: CGPoint
        repeat {
            nextPosition = randomPosition()
        } while nextPosition == position
        let animation = appendAnimation(position: position, nextPosition: nextPosition, totalDuration: totalDuration)
        position = nextPosition
        totalDuration += animation.duration
    }
    // Back to initial position for loop
    let lastAnimation = appendAnimation(position: position, nextPosition: initialPosition, totalDuration: totalDuration)
    totalDuration += lastAnimation.duration
    
    let group = CAAnimationGroup()
    group.animations = animations
    group.duration = totalDuration
    group.repeatCount = Float.infinity
    magnificationMaskLayer.add(group, forKey: "positionAnimation")
    
    func appendAnimation(position: CGPoint, nextPosition: CGPoint, totalDuration: CFTimeInterval) -> CABasicAnimation {
        let animation = CABasicAnimation(keyPath: "position")
        animation.fromValue = position
        animation.toValue = nextPosition
        animation.duration = 1.0 + CFTimeInterval(arc4random() % UInt32(2))
        animation.beginTime = totalDuration
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.isRemovedOnCompletion = false
        animation.fillMode = kCAFillModeForwards
        animations.append(animation)
        return animation
    }
    
    손님들에게 인기가 많으니 다행이다!

    소스 코드


    https://github.com/atsushijike/AnalyzeImageView
    컨디션
    - Xcode 9.3
    - Swift 4.1

    좋은 웹페이지 즐겨찾기