Estoy luchando con un problema con respecto a CGAffineTransform escala y de traducción en la que cuando me puse a transformar en un bloque de animación en una vista que ya tiene una transformación de la vista salta un poco antes de la animación.

Ejemplo:

//somewhere in view did load or during initialization
var view = UIView()
view.frame = CGRectMake(0,0,100,100)
var scale = CGAffineTransformMakeScale(0.8,0.8)
var translation = CGAffineTransformMakeTranslation(100,100)
var concat = CGAffineTransformConcat(translation, scale)
view.transform = transform

//called sometime later
func buttonPressed() {
    var secondScale = CGAffineTransformMakeScale(0.6,0.6)
    var secondTranslation = CGAffineTransformMakeTranslation(150,300)
    var secondConcat = CGAffineTransformConcat(secondTranslation, secondScale)
    UIView.animateWithDuration(0.5, animations: { () -> Void in 
         view.transform = secondConcat
    })

}

Ahora cuando buttonPressed() se llama a la vista salta a la parte superior izquierda de alrededor de 10 píxeles antes de empezar a animar. Sólo he sido testigo de este problema con un concat transformar, utilizando sólo una traducción transformar funciona bien.

Edit: Ya he hecho un montón de investigación sobre el asunto creo que debo mencionar que este problema aparece, independientemente de que sean o no auto de diseño se convierte en

Lo que si uso CGAffineTransformTranslate(secondScale,150,300)?
El resultado es exactamente el mismo
¿Qué significa «salta un poco»? ¿Vuelve a la identidad de transformación? ¿Se animan a secondConcat desde el saltar o no saltar, volver a concat, luego animar a secondConcat?
¿Alguna vez resolver esto? Actualmente la depuración del mismo problema.
por desgracia, yo no. Terminé de envoltura de vista de uno dentro de otro, así que se podría traducir la visión exterior y la escala de la vista interior. De esta manera pude solucionar el problema.

OriginalEl autor matteok | 2015-01-13

5 Comentarios

  1. 38

    Me encontré con el mismo problema, pero no pudo encontrar la fuente exacta del problema. El salto parece aparecen sólo en condiciones muy específicas: Si la vista se anima de una transformación t1 a una transformación t2 y dos transformaciones son una combinación de una escala y de una traducción (que es exactamente tu caso). Dada la siguiente solución, que no tiene sentido para mí, supongo que es un bug en el Núcleo de la Animación.

    Primero, he intentado utilizar CATransform3D en lugar de CGAffineTransform.

    Código antiguo:

    var transform = CGAffineTransformIdentity
    transform = CGAffineTransformScale(transform, 1.1, 1.1)
    transform = CGAffineTransformTranslate(transform, 10, 10)
    view.layer.setAffineTransform(transform)

    Nuevo código:

    var transform = CATransform3DIdentity
    transform = CATransform3DScale(transform, 1.1, 1.1, 1.0)
    transform = CATransform3DTranslate(transform, 10, 10, 0)
    view.layer.transform = transform

    El nuevo código debe ser equivalente a la anterior (el cuarto parámetro es 1.0 o 0 de modo que no hay ninguna escala/la traducción en z dirección), y, de hecho, se muestra el mismo salto. Sin embargo, aquí viene la magia negra: En la escala de la transformación, el cambio, el z parámetro para nada diferente de 1.0, como este:

    transform = CATransform3DScale(transform, 1.1, 1.1, 1.01)

    Este parámetro debe tener ningún efecto, pero ahora el salto se ha ido.

    🎩✨

    Creo que esta respuesta no obtuvo suficientes créditos… he sido de codificación para los días y no podía arreglar esto.
    ☝️Ídem. Tuve el mismo problema con una simple escala y la traducción. La capa de «mover» a la izquierda un poco antes de la animación. La aplicación de un 1.01 escala a la z eje se ha solucionado el problema.

    OriginalEl autor Theo

  2. 4

    Parece Apple UIView animación interna de error. Cuando Apple interpola CGAffineTransform cambios entre dos valores para crear la animación debe hacer los siguientes pasos:

    • Extracto de la traducción, la escala y la rotación de
    • Interpolar valores extraídos del formulario de inicio al final de la
    • Montar CGAffineTransform para cada uno de interpolación paso

    Montaje debe ser en el siguiente orden:

    • Traducción
    • Escala
    • Rotación

    Pero parece que Apple haga la traducción después de la escala y la rotación. Este error debe ser corregido por Apple.

    OriginalEl autor k06a

  3. 0

    Lugar de CGAffineTransformMakeScale() y CGAffineTransformMakeTranslation(), que crea una transformación basados en CGAffineTransformIdentity (básicamente sin transformar), de la que desea escalar y traducir basado en la visión actual de transformación mediante CGAffineTransformScale() y CGAffineTransformTranslate(), que comienza con la transformación existente.

    Yo en realidad necesidad de establecer una absoluta transformación durante la animación, lo que significa que no quiero agregar a la transformación existente pero reemplazarlo animados
    También he intentado usar CGAffineTransformTranslate en lugar de CGAffineTransformMakeTranslate y el problema sigue siendo el mismo.

    OriginalEl autor Dave Batton

  4. 0

    El origen del problema es la falta de información de la perspectiva de la transformación.

    Usted puede agregar la información de la perspectiva de la modificación de la m34 propiedad de su transformación 3d

    var transform = CATransform3DIdentity
    transform.m34 = 1.0 / 200 //your own perspective value here
    transform = CATransform3DScale(transform, 1.1, 1.1, 1.0)
    transform = CATransform3DTranslate(transform, 10, 10, 0)
    view.layer.transform = transform
    Podría por favor explicar un poco más, y también la razón por la este ‘mágicamente’ funciona?

    OriginalEl autor Snit

  5. 0

    , No sé por qué, pero este código puede trabajar

    actualización:

    He conseguido combinar escala, traslación y rotación, de cualquier transformar el estado a cualquier nueva transformación del estado.

    Creo que la transformación es reinterpretada en el inicio de la animación.

    el delimitador de inicio de transformación se considera en nueva transformación, y, a continuación, convertir a la vieja transformar.

    self.v  = UIView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
    self.v?.backgroundColor = .blue
    self.view.addSubview(v!)
    func buttonPressed() {
    let view = self.v!
    let m1 = view.transform
    let tempScale = CGFloat(arc4random()%10)/10 + 1.0
    let tempRotae:CGFloat = 1
    let m2 = m1.translatedBy(x: CGFloat(arc4random()%30), y: CGFloat(arc4random()%30)).scaledBy(x: tempScale, y: tempScale).rotated(by:tempRotae)
    self.animationViewToNewTransform(view: view, newTranform: m2)
    }    
    func animationViewToNewTransform(view: UIView, newTranform: CGAffineTransform) {
    //1. pointInView.apply(view.transform) is not correct point.
    //the real matrix is mAnchorToOrigin.inverted().concatenating(m1).concatenating(mAnchorToOrigin)
    //2. animation begin trasform is relative to final transform in final transform coordinate
    //anchor and mAnchor
    let normalizedAnchor0 = view.layer.anchorPoint
    let anchor0 = CGPoint(x: normalizedAnchor0.x * view.bounds.width, y: normalizedAnchor0.y * view.bounds.height)
    let mAnchor0 = CGAffineTransform.identity.translatedBy(x: anchor0.x, y: anchor0.y)
    //0->1->2
    //let origin = CGPoint(x: 0, y: 0)
    //let m0 = CGAffineTransform.identity
    let m1 = view.transform
    let m2 = newTranform
    //rotate and scale relative to anchor, not to origin
    let matrix1 = mAnchor0.inverted().concatenating(m1).concatenating(mAnchor0)
    let matrix2 = mAnchor0.inverted().concatenating(m2).concatenating(mAnchor0)
    let anchor1 = anchor0.applying(matrix1)
    let mAnchor1 = CGAffineTransform.identity.translatedBy(x: anchor1.x, y: anchor1.y)
    let anchor2 = anchor0.applying(matrix2)
    let txty2 = CGPoint(x: anchor2.x - anchor0.x, y: anchor2.y - anchor0.y)
    let txty2plusAnchor2 = CGPoint(x: txty2.x + anchor2.x, y: txty2.y + anchor2.y)
    let anchor1InM2System = anchor1.applying(matrix2.inverted()).applying(mAnchor0.inverted())
    let txty2ToM0System = txty2plusAnchor2.applying(matrix2.inverted()).applying(mAnchor0.inverted())
    let txty2ToM1System = txty2ToM0System.applying(mAnchor0).applying(matrix1).applying(mAnchor1.inverted())
    var m1New = m1
    m1New.tx = txty2ToM1System.x + anchor1InM2System.x
    m1New.ty = txty2ToM1System.y + anchor1InM2System.y
    view.transform = m1New
    UIView.animate(withDuration: 1.4) {
    view.transform = m2
    }
    }

    Yo también trato el zScale solución, parece que también funcionan si se establece zScale no-1 en la primera transformar o en cada transformación

        let oldTransform = view.layer.transform
    let tempScale = CGFloat(arc4random()%10)/10 + 1.0
    var newTransform = CATransform3DScale(oldTransform, tempScale, tempScale, 1.01)
    newTransform = CATransform3DTranslate(newTransform, CGFloat(arc4random()%30), CGFloat(arc4random()%30), 0)
    newTransform = CATransform3DRotate(newTransform, 1, 0, 0, 1)
    UIView.animate(withDuration: 1.4) {
    view.layer.transform = newTransform
    }

    OriginalEl autor lbsweek

Dejar respuesta

Please enter your comment!
Please enter your name here