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] (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |