How do I save the final state of a neon animation in Polymer?
Is there a way to save the final state of the neon animation? I tried using fill: 'forwards'
, but doesn't seem to do anything.
<template>
<div id="rect" style="width:100px;height:100px;background-color:red"></div>
...
properties: {
animationConfig: {
value: function () {
return {
'hide': [{
name: 'fade-out-animation',
node: this.$.rect,
// this doesn't work!
fill: 'forwards'
}]
}
}
}
},
Basically I want to div
hide after the animation finishes hide
. In the demo, you can see that the red div
disappears, but then reappears immediately after the animation ends.
source to share
I tracked down the source of the problem.
Open neon-animation-runner-behavior.html
and find the function playAnimation
.
Internally this._player.onfinish
, a note is called this._player.cancel()
. This one cancel
is basically
Set the source to null and clear any effects associated with the previous source.
Update
At the end, I added another parameter to the function playAnimation
, so when I need to enforce a final state, I add a flag false
to a function like this -
this.playAnimation('unloadCells', null, false);
This is the safest option I have come up with as it won't interrupt existing Polymer animations on different elements. I'm sure the Polymer team will be able to come up with a great solution in the future, but so far this is doing the trick. :)
playAnimation: function (type, cookie, cancellable) {
// default its value to true so existing stuff won't be affected
cancellable = typeof cancellable !== 'undefined' ? cancellable : true;
var allConfigs = this.getAnimationConfig(type);
if (!allConfigs) {
return;
}
var allAnimations = this._configureAnimationEffects(allConfigs);
var allEffects = allAnimations.map(function(animation) {
return animation.effect;
});
if (allEffects.length > 0) {
this._player = this._runAnimationEffects(allEffects);
this._player.onfinish = function() {
this._completeAnimations(allAnimations);
if (this._player) {
// when manually set to false, this._player.cancel() will be skipped
// so we get to maintain the end state for some scenarios
if (cancellable) {
this._player.cancel();
}
this._player = null;
}
this.fire('neon-animation-finish', cookie, {bubbles: false});
}.bind(this);
} else {
this.fire('neon-animation-finish', cookie, {bubbles: false});
}
},
source to share
Use a listener to detect the end of the animation. Then call the function that hides the div.
properties: {
animationConfig: {
value: function () {
return {
'hide': [{
name: 'fade-out-animation',
node: this.$.rect,
}]
}
}
}
},
listeners: {
// this event is fired when the animation finishes
"neon-animation-finish": "animationComplete"
},
animationComplete: function() {
this.$.rect.style.display = "none";
}
If you have many different animations to listen to to end, use a switch statement to separate each animation.
properties: {
animationConfig: {
value: function () {
return {
'hide': [{
name: 'fade-out-animation',
node: this.$.rect,
}]
}
}
}
},
listeners: {
// this event is fired when the animation finishes
"neon-animation-finish": "animationComplete"
},
animationComplete: function(event, animHandler) {
switch (animHandler) {
case "hide":
this.hideFinished();
break;
case "show":
this.showFinished();
break;
default: null
}
},
hideFinished: function() {
//do something
},
showFinished: function() {
//do something
}
When using this method, you need to add a second parameter to the function playAnimation
that acts as an identifier. Like this:
this.playAnimation("hide", "hide");
Then, for each animation you add, just add another case to the switch statement with the value in the second parameter of the function playAnimation()
. I usually use the same line to keep track of it easily.
source to share