代码之家  ›  专栏  ›  技术社区  ›  Daniel

交互式UIView翻转过渡

  •  2
  • Daniel  · 技术社区  · 7 年前

    private func flipToBack() {
        UIView.transition(from: frontContainer, to: backContainer, duration: 0.5, options: [.transitionFlipFromRight, .showHideTransitionViews], completion: nil)
    }
    
    private func flipToFront() {
        UIView.transition(from: backContainer, to: frontContainer, duration: 0.5, options: [.transitionFlipFromLeft, .showHideTransitionViews], completion: nil)
    }
    

    UIViewPropertyAnimator ,但我不知道如果不从头开始构建翻转动画,我会在animator中设置什么属性的动画。

    是否可以使用 UIViewPropertyImator

    1 回复  |  直到 7 年前
        1
  •  4
  •   Daniel    7 年前

    最后是我自己写的。代码很长,所以这里有一个 the full program 在GitHub上。以下是关键部分:

    所有东西都封装在一个 InteractiveFlipAnimator 具有前视图的对象( v1 )还有后视图( v2 ). 每个视图都有一个黑色的覆盖层,当视图在透视图中转向时,它可以作为阴影来添加变暗效果。

    /// Add a `UIPanGestureRecognizer` to the main view that contains the card and pass it onto this function.
    @objc func pan(_ gesture: UIPanGestureRecognizer) {
        guard let view = gesture.view else { return }
        if isAnimating { return }
    
        let translation = gesture.translation(in: view)
        let x = translation.x
        let angle = startAngle + CGFloat.pi * x / view.frame.width
    
        // If the angle is outside [-pi, 0], then do not rotate the view and count it as touchesEnded. This works because the full width is the screen width.
        if angle < -CGFloat.pi || angle > 0 {
            if gesture.state != .began && gesture.state != .changed {
                finishedPanning(angle: angle, velocity: gesture.velocity(in: view))
            }
            return
        }
    
        var transform = CATransform3DIdentity
        // Perspective transform
        transform.m34 = 1 / -500
        // y rotation transform
        transform = CATransform3DRotate(transform, angle, 0, 1, 0)
        self.v1.layer.transform = transform
        self.v2.layer.transform = transform
    
        // Set the shadow
        if startAngle == 0 {
            self.v1Cover.alpha = 1 - abs(x / view.frame.width)
            self.v2Cover.alpha = abs(x / view.frame.width)
        } else {
            self.v1Cover.alpha = abs(x / view.frame.width)
            self.v2Cover.alpha = 1 - abs(x / view.frame.width)
        }
    
        // Set which view is on top. This flip happens when it looks like the two views make a vertical line.
        if abs(angle) < CGFloat.pi / 2 {
            // Flipping point
            v1.layer.zPosition = 0
            v2.layer.zPosition = 1
        } else {
            v1.layer.zPosition = 1
            v2.layer.zPosition = 0
        }
    
        // Save state
        if gesture.state != .began && gesture.state != .changed {
            finishedPanning(angle: angle, velocity: gesture.velocity(in: view))
        }
    }
    

    完成平移的代码非常相似,但也要长得多。要看到所有这些结合在一起,请访问上面的GitHub链接。

    推荐文章