Red de conocimiento informático - Material del sitio web - Cómo usar Swift para crear hermosas animaciones de transformación de botones

Cómo usar Swift para crear hermosas animaciones de transformación de botones

Podemos crear manualmente una línea corta como esta:

Let shortStroke: CGPath = { let path = CGPathCreateMutable() CGPathMoveToPoint(path, nil, 2, 2) CGPathAddLineToPoint(path, nil, 28, 2) ruta de retorno}()

Pero para la línea recta en el medio, dado que su trayectoria es más compleja, utilicé Sketch para crear una ruta e incorporar animación en la línea recta: < / p>

A continuación, exporté la imagen al formato SVG

A continuación, exporté la imagen al formato SVG, luego convertí la imagen en un fragmento de código a través de PaintCode 1 y la importé a la mitad del proyecto. . A continuación, reescribí el fragmento de código importado y creé el objeto CGPath requerido:

let sketch: CGPath = { let path = CGPathCreateMutable() CGPathMoveToPoint(path, nil, 10, 27) CGPathAddCurveToPoint(path, nil, 12.00, 27.00, 28.02, 27.00, 40, 27) CGPathAddCurveToPoint(ruta, nulo, 55.92, 27.00, 50.47,2.00, 27,2) 2.00,2.00,13.16, 2, 27) CGPathAddCurveToPoint(ruta, nulo,2 .00, 40.84, 13.16, 52.00, 27, 52) CGPathAddCurveToPoint(ruta, nil, 40.84, 52.00, 52.00, 40.84, 52, 27) CGPathAddCurveToPoint(ruta, n il, 52.00, 13.16, 42.39,2.00, 27,2) GPathAddCurveToPoint(ruta, nula , 13.16,2.00,2.00, 13.16,2, 27) devuelve ruta}()

Tal vez haya una biblioteca de terceros que le permita convertir SVG Convert a CGPath directamente, pero no es necesario eliminarlo la gallina de los huevos con esta sencilla imagen.

En mi subclase personalizada de UIButton, agregué tres CAShapeLabs.

Agregué tres propiedades CAShapeLayer y las asocié con las rutas definidas previamente:

self.top.path = shortStrokeself.middle.path = contornoself.bottom.path = shortStroke

Luego configuré el propiedades relevantes:

layer.fillColor = nillayer.fillColor = nillayer.fillColor = nillayer.fillColor = nillayer.fillColor = nillayer.fillColorfillColor = nillayer.strokeColor = UIColor.whiteColor().CGColorlayer lineWidth = 4layer. miterLimit = 4layer.lineCap = kCALineCapRoundlayer.masksToBounds = true

Para calcular los límites (?bounds?) correctamente, necesito determinar el tamaño de estas líneas. Afortunadamente, la ruta creada por la función CGPathCreateCopyByStrokingPath tiene el mismo aspecto que la línea original, por lo que sus "límites" son exactamente del mismo tipo que "CAShapeLayer" en el parámetro:

letboundingPath = CGPathCreateCopyByStrokingPath(layer. path, nil, 4, kCGLineCapRound, kCGLineJoinMiter, 4) Layer.bounds = CGPathGetPathBoundingBox(boundingPath)

Debido a que las líneas superior e inferior del botón de hamburguesa se rotarán a continuación alrededor del punto más a la derecha, debemos establecer ellos en consecuencia durante el diseño Punto de anclaje (? punto de anclaje?):

self.top.anchorPoint = CGPointMake(28.0 / 30.0, 0.5)self.top.position = CGPointMake(40, 18)self.middle. posición = CGPointMake( 27, 27)self.middle.strokeStart = hamburgerStrokeStartself.middle.strokeEnd = hamburgerStrokeEndself.bottom.anchorPoint = CGPointMake(28.0 / 30.0, 0.5)self.bottom.position = CGPointMake(40, 36)

Siguiente Parte de esto es animación. Cuando el estado del botón cambia, las tres líneas deberían moverse dinámicamente a sus nuevas posiciones. Para las dos líneas rectas del exterior, esto es fácil de lograr.

Por ejemplo, para la línea en la parte superior, la moví 4 puntos hacia adentro para que estuviera centrada, luego la giré 45 grados en sentido antihorario, creando media X:

var transform = CATransform3DIdentitytransform = CATransform3DTranslate ( transform, -4, 0, 0)transform = CATransform3DRotate(transform, -M_PI_4, 0, 0, 1)let animación = CABasicAnimation(keyPath: "transform")animation .fromValue = NSValue(CATransform3D: CATransform3DIdentity)animation.toValue = NSValue(CATransform3D : transform)animation.timingFunction = CAMediaTimingFunction(controlPoints: 0,25, -0,8, 0,75, 1,85) animación. comenzarTime = CACurrentMediaTime() + 0.25self.top.addAnimation( animación, forKey: "transform")self.top.transform=transform

La parte inferior de esta línea se proporciona como un ejercicio para el lector.

A continuación, la línea media parece un poco complicada. Para lograr el efecto deseado, necesitamos animar el punto inicial y final de CAShapeLayer respectivamente.

Primero, necesito saber cuáles son los valores de estas dos propiedades en los dos estados. Tenga en cuenta que incluso en el estado de hamburguesa, el punto inicial de la línea no es O.

El camino se extiende ligeramente desde la izquierda, podemos aplicar la función "timing" más tarde para lograr efectos geniales:

let menuStrokeStart:CGFloat = 0.325let menuStrokeEnd:CGFloat = 0.9let hamburgerStrokeStart.CGFloat = 0.028let hamburgerStrokeEnd: CGFloat = 0.111

A continuación, simplemente creamos la animación y la agregamos a la capa:

let StrokeStart = CABasicAnimation(keyPath: "strokeStart")strokeStart.fromValue = hamburgerStrokeStartStrokeStart.toValue = menuStrokeStart.toValue = menuStrokeStart.toValue = menuStrokeStart.toValue = menuStrokeStart.toValuetoValue = menuStrokeStartstrokeStart.duration = 0.5strokeStart.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)self.middle.addAnimation(strokeStart, forKey: "stro keInicio ")self.middle.strokeStart.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)strokeStart = menuStrokeStartlet StrokeEnd = CABasicAnimation(keyPath: "strokeEnd")strokeEnd.fromValue = hamburgerStrokeEndstrokeEnd.toValue = menuStrokeEndstrokeEnd. duración = 0.6 final del trazo .timingFunction = CAMediaTimingFunction(Puntos de control: 0.25, -0.4, 0.5, 1)self.middle.addAnimation(strokeEnd, forKey: "strokeEnd")self.middle.strokeEnd = menuStrokeEnd

Completo Puedes ver el siguientes resultados del trabajo anterior: