加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 当superView的比例改变时,绘制路径的CABasicAnimation

发布时间:2020-12-14 04:56:08 所属栏目:百科 来源:网络整理
导读:我有一个绘制矩形到特定百分比的动画. 为此,我正在绘制一个CAShapeLayer: func drawTheLayer() - CAShapeLayer { let lineWidth: CGFloat = borderWidth * bounds.size.width / standardSizeWidth let cornerRadiusResized: CGFloat = cornerRadiusRanged *
我有一个绘制矩形到特定百分比的动画.

为此,我正在绘制一个CAShapeLayer:

func drawTheLayer() -> CAShapeLayer {

    let lineWidth: CGFloat = borderWidth * bounds.size.width / standardSizeWidth
    let cornerRadiusResized: CGFloat = cornerRadiusRanged * bounds.size.width / standardSizeWidth
    let insetRect = CGRectInset(bounds,lineWidth/2.0,lineWidth/2.0)
    let apath = ShapeDraw.createRoundedCornerPath(insetRect,cornerRadius: cornerRadiusResized,percent: percentageRanged)
    let apathLayer = CAShapeLayer()

    apathLayer.frame = bounds
    apathLayer.bounds = insetRect
    apathLayer.path = apath
    apathLayer.strokeColor = AppColor.OnColor.CGColor
    apathLayer.fillColor = nil
    apathLayer.lineWidth = lineWidth
    apathLayer.lineJoin = kCALineJoinRound
    apathLayer.lineCap = kCALineCapRound
    apathLayer.geometryFlipped = true

    let flipTransform = CGAffineTransformMakeScale(1,-1)

    apathLayer.setAffineTransform(flipTransform)
    return apathLayer

}

要为绘图设置动画:

func animateToLevel() {
    if percentage <= 0 {
        return
    }

    pathLayer?.removeFromSuperlayer()
    pathLayer?.removeAllAnimations()

    animating = true
    let apathLayer = drawTheLayer()
    layer.addSublayer(apathLayer)
    let pathAnimation = CABasicAnimation(keyPath: "strokeEnd")
    pathAnimation.delegate = self
    pathAnimation.duration = 0.5
    pathAnimation.fromValue = 0.0
    pathAnimation.setValue("levelAnimation",forKey: "animationId")
    apathLayer.addAnimation(pathAnimation,forKey: nil)

    pathLayer = apathLayer
}

与这个动画无关,还有另一个动画可以发生.缩放矩形的superView.当我开始绘制路径时出现问题是根据小尺寸的超级视图绘制的,然后当帧变大时,绘图动画的路径保持相同,这是预期但是有一个逻辑上没有hacky解决方案吗?或者我必须在drawRect中执行此操作

对于superview,动画在UIView动画中更改UILayout高度常量:

heightOfContainerConstraint.constant = 100 // or 400 when it is expanded
UIView.animateWithDuration(animated ? animationDuration : 0) {
    self.view.layoutIfNeeded()
}

创建圆角的代码:

import UIKit

class ShapeDraw {

static func createRoundedCornerPath(rect: CGRect,cornerRadius: CGFloat,percent: CGFloat) -> CGMutablePathRef {

    let piNumber: CGFloat = CGFloat(M_PI)

    // get the 4 corners of the rect
    let topLeft = CGPointMake(rect.origin.x,rect.origin.y)
    let topRight = CGPointMake(rect.origin.x + rect.size.width,rect.origin.y)
    let bottomRight = CGPointMake(rect.origin.x + rect.size.width,rect.origin.y + rect.size.height)
    let bottomLeft = CGPointMake(rect.origin.x,rect.origin.y + rect.size.height)

    // Set 4 corner arc starting angles
    let startAngleTopRight: CGFloat = 3 * piNumber/2
    let startAngleBottomRight: CGFloat = 0
    let startAngleBottomLeft: CGFloat = piNumber / 2
    let startAngleTopLeft: CGFloat = piNumber

    let slices = (CGRectGetWidth(rect) / cornerRadius) * 4
    let partValue: CGFloat = 100 / slices // %100 is total -> 1 piece is 100/16 percent

    let wayToGoLine = CGRectGetWidth(rect) - 2 * cornerRadius
    let linePartValue = partValue * (slices/4 - 2)

    var remainingPercent: CGFloat = percent
    let path = CGPathCreateMutable()
    // move to top left
    CGPathMoveToPoint(path,nil,topRight.x/2,topRight.y)

    // add top right half line
    remainingPercent = addLine(path,x: topRight.x/2 + (wayToGoLine/2 * getConstantForThis(remainingPercent,partValue: linePartValue/2)),y: topRight.y,remainingPercent: remainingPercent,currentPartPercent: linePartValue/2)

    // add top right curve
    let endingAngleTopRight = endingAngleForThis(startAngleTopRight,partValue: partValue)
    remainingPercent =  addArc(path,x: topRight.x - cornerRadius,y: topRight.y + cornerRadius,radius: cornerRadius,startAngle: startAngleTopRight,endingAngle: endingAngleTopRight,currentPartPercent: partValue * 2)

    // add right line
    remainingPercent = addLine(path,x: bottomRight.x,y: topRight.y + cornerRadius + (wayToGoLine * getConstantForThis(remainingPercent,partValue: linePartValue)),currentPartPercent: linePartValue)

    // add bottom right curve
    let endingAngleBottomRight = endingAngleForThis(startAngleBottomRight,partValue: partValue)
    remainingPercent = addArc(path,x: bottomRight.x - cornerRadius,y: bottomRight.y - cornerRadius,startAngle: startAngleBottomRight,endingAngle: endingAngleBottomRight,currentPartPercent: partValue * 2)

    // add bottom line
    remainingPercent = addLine(path,x: bottomRight.x - cornerRadius - (wayToGoLine * getConstantForThis(remainingPercent,y: bottomLeft.y,currentPartPercent: linePartValue)

    // add bottom left curve
    let endingAngleBottomLeft = endingAngleForThis(startAngleBottomLeft,x: bottomLeft.x + cornerRadius,y: bottomLeft.y - cornerRadius,startAngle: startAngleBottomLeft,endingAngle: endingAngleBottomLeft,currentPartPercent: partValue * 2)

    // add left line
    remainingPercent = addLine(path,x: topLeft.x,y: bottomLeft.y - cornerRadius - (wayToGoLine * getConstantForThis(remainingPercent,currentPartPercent: linePartValue)

    // add top left curve
    let endingAngleTopLeft = endingAngleForThis(startAngleTopLeft,x: topLeft.x + cornerRadius,y: topLeft.y + cornerRadius,startAngle: startAngleTopLeft,endingAngle: endingAngleTopLeft,currentPartPercent: partValue * 2)

    // add top left half line
    remainingPercent = addLine(path,x: topLeft.x + cornerRadius + (wayToGoLine/2 * getConstantForThis(remainingPercent,currentPartPercent: linePartValue/2)

    return path
}

static func endingAngleForThis(startAngle: CGFloat,remainingPercent: CGFloat,partValue: CGFloat) -> CGFloat {
    return startAngle + (CGFloat(M_PI) * getConstantForThis(remainingPercent,partValue: partValue * 2) / 2)
}

static func getConstantForThis(percent: CGFloat,partValue: CGFloat) -> CGFloat {
    let percentConstant = percent - partValue > 0 ? 1 : percent / partValue
    return percentConstant
}

static func addLine(path: CGMutablePath?,x: CGFloat,y: CGFloat,currentPartPercent: CGFloat) -> CGFloat {
    if remainingPercent > 0 {
        CGPathAddLineToPoint(path,x,y)
        return remainingPercent - currentPartPercent
    }
    return 0
}

static func addArc(path: CGMutablePath?,radius: CGFloat,startAngle: CGFloat,endingAngle: CGFloat,currentPartPercent: CGFloat) -> CGFloat {
    if remainingPercent > 0 {

        CGPathAddArc(path,y,radius,startAngle,endingAngle,false)
        return remainingPercent - currentPartPercent
    }
    return 0
}

}

解决方法

基本上,我们有两个动画:

>按照矩形路径指定特定百分比
>缩放矩形超视图或更改边界的动画

目标是:这些动画必须在同一时间(一组)一起工作,而不是顺序.

下面的代码只是一个示例,不遵循确切的属性或自定义目标,我想解释在这种情况下我会做什么:

// follow the rectangle path
    let pathAnimation = CABasicAnimation(keyPath: "strokeEnd")
    let cornerRadiusResized: CGFloat = cornerRadiusRanged * bounds.size.width / standardSizeWidth
    let apath = ShapeDraw.createRoundedCornerPath(insetRect,percent: percentageRanged)
    pathAnimation.toValue = apath

    // scaling of the rectangle superview
    let newBounds = CGRectMake(self.view.bounds.origin.x,self.view.bounds.origin.y,self.view.bounds.width,self.view.bounds.height)
    let boundsAnimation = CABasicAnimation(keyPath: "bounds")
    boundsAnimation.toValue = NSValue(CGRect:newBounds)

    // The group
    var theGroup: CAAnimationGroup = CAAnimationGroup()
    theGroup.animations = [pathAnimation,boundsAnimation]
    theGroup.duration = 2.0
    theGroup.repeatCount = 1
    theGroup.fillMode = kCAFillModeForwards
    apathLayer.addAnimation(theGroup,forKey: "theGroup")

编辑:

如果您需要第三个动画,当您在评论中发言时,要更改UIButton尺寸,您还可以添加:

var buttonAnimation:CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
pulseAnimation.duration = 2.0
pulseAnimation.toValue = NSNumber(float: 0.5)
pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaSEOut)

并将其添加到数组中:

theGroup.animations = [pathAnimation,buttonAnimation,boundsAnimation]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读