У меня есть анимация рисования прямоугольника с определенным процентом его.CABasicИзменение чертежа пути не масштабируется при изменении масштаба шкалы супервизора
Для этого я рисую 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
. Проблема возникает, когда я начинаю рисовать путь, рисуется в соответствии с малым размером superView, а затем, когда кадр становится больше, путь анимации рисования остается таким же, как ожидалось, но есть ли для этого логическое не хакерское решение? Или я должен сделать это в drawRect
Для надтаблицы анимация изменения постоянной высоты UILayout в качестве UIView анимации:
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, remainingPercent: remainingPercent, partValue: partValue)
remainingPercent = addArc(path, x: topRight.x - cornerRadius, y: topRight.y + cornerRadius, radius: cornerRadius, startAngle: startAngleTopRight, endingAngle: endingAngleTopRight, remainingPercent: remainingPercent, currentPartPercent: partValue * 2)
// add right line
remainingPercent = addLine(path, x: bottomRight.x, y: topRight.y + cornerRadius + (wayToGoLine * getConstantForThis(remainingPercent, partValue: linePartValue)), remainingPercent: remainingPercent, currentPartPercent: linePartValue)
// add bottom right curve
let endingAngleBottomRight = endingAngleForThis(startAngleBottomRight, remainingPercent: remainingPercent, partValue: partValue)
remainingPercent = addArc(path, x: bottomRight.x - cornerRadius, y: bottomRight.y - cornerRadius, radius: cornerRadius, startAngle: startAngleBottomRight, endingAngle: endingAngleBottomRight, remainingPercent: remainingPercent, currentPartPercent: partValue * 2)
// add bottom line
remainingPercent = addLine(path, x: bottomRight.x - cornerRadius - (wayToGoLine * getConstantForThis(remainingPercent, partValue: linePartValue)), y: bottomLeft.y, remainingPercent: remainingPercent, currentPartPercent: linePartValue)
// add bottom left curve
let endingAngleBottomLeft = endingAngleForThis(startAngleBottomLeft, remainingPercent: remainingPercent, partValue: partValue)
remainingPercent = addArc(path, x: bottomLeft.x + cornerRadius, y: bottomLeft.y - cornerRadius, radius: cornerRadius, startAngle: startAngleBottomLeft, endingAngle: endingAngleBottomLeft, remainingPercent: remainingPercent, currentPartPercent: partValue * 2)
// add left line
remainingPercent = addLine(path, x: topLeft.x, y: bottomLeft.y - cornerRadius - (wayToGoLine * getConstantForThis(remainingPercent, partValue: linePartValue)), remainingPercent: remainingPercent, currentPartPercent: linePartValue)
// add top left curve
let endingAngleTopLeft = endingAngleForThis(startAngleTopLeft, remainingPercent: remainingPercent, partValue: partValue)
remainingPercent = addArc(path, x: topLeft.x + cornerRadius, y: topLeft.y + cornerRadius, radius: cornerRadius, startAngle: startAngleTopLeft, endingAngle: endingAngleTopLeft, remainingPercent: remainingPercent, currentPartPercent: partValue * 2)
// add top left half line
remainingPercent = addLine(path, x: topLeft.x + cornerRadius + (wayToGoLine/2 * getConstantForThis(remainingPercent, partValue: linePartValue/2)), y: topRight.y, remainingPercent: 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, remainingPercent: CGFloat, currentPartPercent: CGFloat) -> CGFloat {
if remainingPercent > 0 {
CGPathAddLineToPoint(path, nil, x, y)
return remainingPercent - currentPartPercent
}
return 0
}
static func addArc(path: CGMutablePath?, x: CGFloat, y: CGFloat, radius: CGFloat, startAngle: CGFloat, endingAngle: CGFloat, remainingPercent: CGFloat, currentPartPercent: CGFloat) -> CGFloat {
if remainingPercent > 0 {
CGPathAddArc(path, nil, x, y, radius, startAngle, endingAngle, false)
return remainingPercent - currentPartPercent
}
return 0
}
}
@AlessandroOrnano я добавил код, но я не думаю, что это необходимо, чтобы один возвращается в CGMutablePathRef и сама функция не имеет большого значения. –
Я добавил экран gif также, надеюсь, что кто-то ответит сейчас: D @AlessandroOrnano –
Хорошо, это ясный вопрос. Я не знаю, правильно ли я понимаю, но я попытался дать ответ. –