You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带圆角衔接效果的形状过渡动画?

实现矩形衔接处带圆角的过渡动画方案

我需要实现从最左侧形状到最右侧形状的过渡动画,核心难点是中间帧里两个矩形衔接处的圆角效果。

当前我用三个视图实现的代码如下:

class TestRoundedCornerViews: UIView {
    
    let leftView = UIView()
    let middleView = UIView()
    let rightView = UIView()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        let cornerRadius: CGFloat = 16
        
        leftView.layer.cornerRadius = cornerRadius
        leftView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner]
        self.addSubview(self.leftView)
        
        middleView.layer.cornerRadius = cornerRadius
        middleView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
        self.addSubview(self.middleView)
        
        rightView.layer.cornerRadius = cornerRadius
        rightView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
        self.addSubview(self.rightView)
        
    }
    
    // MARK: Layout
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        let leftSideWidth: CGFloat = 100
        
        let leftViewWidth: CGFloat = leftSideWidth / 2
        let middleViewWidth: CGFloat = leftViewWidth
        
        let rightViewWidth: CGFloat = 40
        
        leftView.frame = CGRect(
            x: 0,
            y: 0,
            width: leftViewWidth,
            height: self.bounds.height
        )
        
        middleView.frame = CGRect(
            x: leftView.frame.maxX,
            y: 0,
            width: middleViewWidth,
            height: self.bounds.height
        )
        
        rightView.frame = CGRect(
            x: middleView.frame.maxX,
            y: 0,
            width: rightViewWidth,
            height: self.bounds.height
        )
        
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }

}

目前的实现效果里,视图衔接处没有圆角,而且不知道怎么完成到最终形状的过渡动画。


解决方案:用CAShapeLayer实现路径动画

不用三个独立视图,改用CAShapeLayer绘制完整路径,通过动画路径的变化来实现过渡,这样能精准控制衔接处的圆角效果。

具体实现代码

class RoundedTransitionView: UIView {
    private let shapeLayer = CAShapeLayer()
    private let cornerRadius: CGFloat = 16
    // 0对应初始态,1对应最终态,控制动画进度
    private var transitionProgress: CGFloat = 0 {
        didSet {
            updateShapePath()
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupBaseLayer()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupBaseLayer() {
        shapeLayer.fillColor = UIColor.systemBlue.cgColor // 可根据需求修改颜色
        layer.addSublayer(shapeLayer)
        updateShapePath()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        updateShapePath()
    }
    
    // 根据进度动态生成路径
    private func updateShapePath() {
        let path = UIBezierPath()
        let totalHeight = bounds.height
        
        // 初始态与最终态的宽度参数,可根据你的实际需求调整
        let initialLeftWidth: CGFloat = 100
        let finalLeftWidth: CGFloat = 60
        let rightBarWidth: CGFloat = 40
        
        // 计算当前状态下的各部分宽度和位置
        let currentLeftWidth = initialLeftWidth - (initialLeftWidth - finalLeftWidth) * transitionProgress
        let rightBarX = currentLeftWidth + (initialLeftWidth - currentLeftWidth) * transitionProgress
        
        // 绘制左侧矩形的左上角圆角
        path.move(to: CGPoint(x: cornerRadius, y: 0))
        path.addArc(withCenter: CGPoint(x: cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: .pi * 1.5, endAngle: .pi, clockwise: false)
        
        // 左侧矩形的左下角圆角
        path.addLine(to: CGPoint(x: 0, y: totalHeight - cornerRadius))
        path.addArc(withCenter: CGPoint(x: cornerRadius, y: totalHeight - cornerRadius), radius: cornerRadius, startAngle: .pi, endAngle: .pi * 0.5, clockwise: false)
        
        // 左侧底部到衔接处的圆角
        path.addLine(to: CGPoint(x: currentLeftWidth, y: totalHeight))
        let bottomCornerCenterX = currentLeftWidth + cornerRadius * transitionProgress
        path.addArc(withCenter: CGPoint(x: bottomCornerCenterX, y: totalHeight - cornerRadius), radius: cornerRadius, startAngle: .pi * 0.5, endAngle: 0, clockwise: false)
        
        // 衔接处到右侧条的底部
        path.addLine(to: CGPoint(x: rightBarX + rightBarWidth, y: totalHeight))
        
        // 右侧条的右下角圆角
        path.addArc(withCenter: CGPoint(x: rightBarX + rightBarWidth - cornerRadius, y: totalHeight - cornerRadius), radius: cornerRadius, startAngle: 0, endAngle: .pi * 0.5, clockwise: true)
        
        // 右侧条的右上角圆角
        path.addLine(to: CGPoint(x: rightBarX + rightBarWidth, y: cornerRadius))
        path.addArc(withCenter: CGPoint(x: rightBarX + rightBarWidth - cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: .pi * 0.5, endAngle: .pi * 1.5, clockwise: true)
        
        // 右侧条顶部到衔接处的圆角
        path.addLine(to: CGPoint(x: rightBarX, y: 0))
        let topCornerCenterX = currentLeftWidth + cornerRadius * (1 - transitionProgress)
        path.addArc(withCenter: CGPoint(x: topCornerCenterX, y: cornerRadius), radius: cornerRadius, startAngle: .pi * 1.5, endAngle: .pi, clockwise: false)
        
        // 回到起点闭合路径
        path.addLine(to: CGPoint(x: cornerRadius, y: 0))
        
        shapeLayer.path = path.cgPath
    }
    
    // 调用这个方法启动过渡动画
    func startTransition() {
        let animation = CABasicAnimation(keyPath: "transitionProgress")
        animation.fromValue = 0
        animation.toValue = 1
        animation.duration = 1.5 // 动画时长可调整
        animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        animation.fillMode = .forwards
        animation.isRemovedOnCompletion = false
        self.layer.add(animation, forKey: "shapeTransition")
        
        // 同步更新属性,确保动画结束后状态正确
        transitionProgress = 1
    }
}

关键说明

  • 用单个CAShapeLayer替代多视图方案,通过动态生成路径实现衔接处的圆角过渡,动画过程中路径平滑变化,不会出现生硬的拼接问题。
  • transitionProgress变量控制动画进度,从0到1对应初始态到最终态,你可以根据实际需求调整初始和最终的宽度参数。
  • 衔接处的圆角通过动态计算圆心位置实现,随着进度变化,圆心逐步移动,让圆角自然过渡消失或出现。

内容的提问来源于stack exchange,提问作者Miles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:25:18