I'm using Ember and Liquid Fire to create some interesting material-design-inspired animated transitions between routes.
I've created two transitions. The first occurs during the transition from the index
route to the about
route and uses the explode
, flyTo
, and toLeft
transitions successfully. Here I match by a data-nav
attribute on both routes to create a smooth, seamless transition that makes the matched element appear to move across the screen to the next page as it flies left. Thumbs up!
The second occurs during the transition from the about
route back to the index
route. Here I match a different element than above by a data-text
attribute on both routes, however unlike the example above, the elements are not identical. Specifically, the font-size is different. Unfortunately this has an undesired effect of immediately displaying the larger font-size text and then having it fly across the page.
What I'd like to do is add an additional transition that animates the font-size. Sounds simple enough.
Below is my initial transitions.js
file with the two transitions described above.
export default function() {
var duration = 1000;
this.transition(
// --------------------- INDEX to ABOUT ----------------------------------- //
this.fromRoute('index'),
this.toRoute('about'),
this.use('explode', {
matchBy: 'data-nav',
use: [ 'flyTo', { duration } ]
}, {
use: [ 'toLeft', { duration } ]
}),
// --------------------- ABOUT to INDEX ----------------------------------- //
this.reverse('explode', {
matchBy: 'data-text',
use: [ 'flyTo', { duration } ]
}, {
use: [ 'toRight', { duration } ]
})
);
}
I believe the answer is to create my own custom transition, however it is turning out to be rather challenging. I created a custom transition called scale-font.js
and added it to my transitions.js
file for this transition.
import { animate, Promise } from "liquid-fire";
export default function scaleFont(opts={}) {
// returns a Promise that resolves when the transition is done
if (!this.newElement) {
return Promise.resolve();
} else if (!this.oldElement) {
this.newElement.css({visibility: ''});
return Promise.resolve();
}
var oldFontSize = this.oldElement.css('font-size');
var newFontSize = (opts.selector ? this.newElement.find(opts.selector) : this.newElement).css('font-size');
this.newElement.css({ visibility: 'hidden' });
return animate(
this.oldElement,
{ fontSize: oldFontSize },
{ duration: 1000 }
).then(() => {
return animate(
this.newElement,
{ fontSize: newFontSize },
{ duration: 1000, visibility: 'visible' }
);
});
}
Unfortunately this doesn't quite work. The first problem is that the oldFontSize
is not correct. It ends up grabbing the new font size. The second problem is no font scaling occurs.
I've researched animating fonts, so I am fairly certain it can be done. Suggestions?