Project download link
non credo che sia necessario lasciare al quarzo per raggiungere questo obiettivo la riproduzione. Tutto ciò che hai descritto e tutto ciò che ho ricavato dall'incombenza di Impress.js sembra essere replicabile attraverso l'applicazione di trasformazioni (principalmente 2D, alcune 3D) a un set di UILabels aggiunto a una vista contenitore che può essere spostata liberamente all'interno vista principale
Per fare questo, il progetto ho creato utilizza una sottoclasse di UILabel
dal titolo "ImpressLabel" con una funzione di init in più in cui invece di passare l'etichetta di un fotogramma, si passa una dimensione, un punto centrale e un CGFloat
per la rotazione dell'etichetta sull'asse Z. Questa trasformazione viene applicata all'istanza all'istanziazione in modo tale che quando si impostano le etichette verranno visualizzate sullo schermo già nella posizione e nella trasformazione specificate.
Quindi, per quanto riguarda la configurazione del testo, è possibile passare l'etichetta a NSAttributedString
anziché a NSString
. Questo vi permette di modificare diverse parti della stringa in modo indipendente, così diverse parole del marchio possono essere diverse dimensioni, font, colori, colori di sfondo, ecc Ecco un esempio dei due paragrafi precedenti:
ImpressLabel *label1 = [[ImpressLabel alloc] initWithSize:CGSizeMake(260.0f, 80.0f) andCenterPointInSuperview:CGPointMake(500.0f, 500.0f) andRotationInSuperview:0.0f andEndingScaleFactor:1.3];
NSMutableAttributedString *firstLabelAttributes = [[NSMutableAttributedString alloc] initWithString:@"then you should try\nimpress.js*\n* no rhyme intended"];
[firstLabelAttributes addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:label1.font.pointSize - 2]
range:NSMakeRange(0, 19)];
[firstLabelAttributes addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:label1.font.pointSize - 8]
range:NSMakeRange(firstLabelAttributes.string.length - 19, 19)];
[firstLabelAttributes addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:label1.font.pointSize + 14]
range:NSMakeRange(23, 11)];
[label1 setNumberOfLines:3];
[label1 setAttributedText:firstLabelAttributes];
[label1 setTextAlignment:NSTextAlignmentCenter];
[containmentView addSubview:label1];
Ora, a più del fegato di tutta l'operazione. Come accennato in precedenza, questa sottoclasse aggiunge un tocco di tocco a ciascuna etichetta. Quando viene riconosciuto un tocco, accadono alcune cose. La vista contenente le etichette eseguirà il pan/back/away regolandone la scala. Inoltre, inizierà a ruotare e regolerà il suo punto di ancoraggio nella vista principale in modo che quando l'animazione si arresta, l'etichetta selezionata sarà centrata sullo schermo con l'orientamento corretto. Poi, naturalmente, mentre tutto sta andando sull'alfa dell'etichetta selezionata verrà portato a 1.0f mentre l'alfa del resto verrà abbassato a 0.25f.
- (void)tapForRotationDetected:(UITapGestureRecognizer *)sender {
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
[scale setToValue:[NSNumber numberWithFloat:0.8]];
[scale setAutoreverses:YES];
[scale setDuration:0.3];
//Create animation to adjust the container views anchorpoint.
CABasicAnimation *adjustAnchor = [CABasicAnimation animationWithKeyPath:@"anchorPoint"];
[adjustAnchor setFromValue:[NSValue valueWithCGPoint:self.superview.layer.anchorPoint]];
[adjustAnchor setToValue:[NSValue valueWithCGPoint:CGPointMake(self.center.x/self.superview.frame.size.width, self.center.y/self.superview.frame.size.height)]];
[adjustAnchor setRemovedOnCompletion:NO];
[adjustAnchor setFillMode:kCAFillModeForwards];
//Create animation to rotate the container view within its superview.
CABasicAnimation *rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
//Create the animation group to apply these transforms
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
[animationGroup setAnimations:@[adjustAnchor,rotation]];
[animationGroup setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[animationGroup setDuration:0.6];
//Apply the end results of the animations directly to the container views layer.
[self.superview.layer setTransform:CATransform3DRotate(CATransform3DIdentity, DEGREES_TO_RADIANS(-self.rotationInSuperview), 0.0f, 0.0f, 1.0f)];
[self.superview.layer setAnchorPoint:CGPointMake(self.center.x/self.superview.frame.size.width, self.center.y/self.superview.frame.size.height)];
[self.superview.layer addAnimation:animationGroup forKey:@"animationGroup"];
//Animate the alpha property of all ImpressLabels in the container view.
[self.superview bringSubviewToFront:self];
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
for (ImpressLabel *label in sender.view.superview.subviews) {
if ([label isKindOfClass:[ImpressLabel class]]) {
if (label != self) {
[label setAlpha:0.25f];
}else{
[label setAlpha:1.0f];
}
}
}
} completion:nil];
}
Ora, per risolvere alcuni dei dubbi elencati nella domanda.
ho fatto il profilo di questo progetto in strumento di assegnazioni Instruments' e consuma solo circa 3,2 MB generale, in modo direi che questo approccio è abbastanza efficace.
L'esempio che ho fornito anima la maggior parte degli oggetti nello spazio 2D, con l'eccezione dell'animazione di ridimensionamento che è un'illusione nella migliore delle ipotesi. Quello che ho fatto qui vuole essere un esempio di come questo possa essere fatto e non è una dimostrazione completa al 100% perché, come ho affermato sopra, l'animazione non è la mia area di competenza. Tuttavia, esaminando i documenti, sembra che la chiave per far ruotare un'etichetta nella terza dimensione e regolarne la panoramica per ruotare tutte le etichette e lasciare l'etichetta selezionata piatta sia l'uso di CATransform3DInvert()
. Anche se non ho ancora avuto il tempo di capire che funziona, sembra che potrebbe essere esattamente ciò che è necessario in questo scenario.
Per quanto riguarda il mirroring, non credo che ci saranno problemi con il ridimensionamento corretto di tutto. Osservando Apple Multiple Display Programming Guide, sembra che l'oggetto passato a NSNotification
UIScreenDidConnectNotification
sia un oggetto UIScreen
. Poiché questo è il caso, è possibile richiedere facilmente questo limite di visualizzazione e regolare di conseguenza i fotogrammi delle etichette e la vista del contenitore.
Nota: In questo esempio, solo 0, 90, 180, e -90 gradi trasforma animati correttamente 100%, a causa coordinate del punto di ancoraggio vengono generati in modo errato. Sembra che la soluzione risieda nello CGPointApplyAffineTransform(<#CGPoint point#>, <#CGAffineTransform t#>)
, ma ancora una volta non ho avuto tutto il tempo per giocarci come avrei voluto. Ad ogni modo, questo dovrebbe essere abbastanza per iniziare con la tua riproduzione.
Questo ha sicuramente suscitato il mio interesse e quando avrò la possibilità di lavorare di nuovo su questo, aggiornerò volentieri questo post con qualsiasi nuova informazione. Spero che questo ti aiuti!
In ogni caso, dare un'occhiata a CATransformLayer come metodo per raggruppare i livelli e trasformarli. –
Domanda aggiornata per concentrarsi sul consumo di memoria dopo il ridimensionamento di un UILabel. La domanda precedente era troppo ampia (e chiusa in quanto tale). Mentre la risposta attualmente accettata è fantastica, non affronta il problema nella domanda aggiornata. Mentre vorrei mettere un altro taglie su di esso, ho un piccolo rappresentante per farne cadere altri 500. – Luke