OptionalkeyframesPerforms any necessary operations/computations and then returns keyframes (Keyframes).
Keyframes, either in the form of a PropertyIndexedKeyframes object or—more commonly—an array of Keyframe objects.
const clipFactories = webchalk.createAnimationClipFactories({
additionalEntranceEffectBank: {
// -----------------------------------------------------------------
// ----------------------------EXAMPLE 1----------------------------
// -----------------------------------------------------------------
// Let us pretend you made this preset entrance animation effect named 'zoomIn'.
// For this animation, you wrote the forward keyframes generator and
// then verified that the desired rewinding effect is exactly equivalent
// to playing the keyframes produced by keyframesGenerator_play() in reverse,
// so you omit keyframesGenerator_rewind.
zoomIn: {
buildFrameGenerators(initialScale: number) {
// return EffectFrameGeneratorSet
return {
keyframesGenerator_play: () => {
console.log('About to return keyframes!');
// return Keyframes (Keyframe[])
return [
{scale: initialScale, opacity: 0}, // Keyframe 1
{} // Keyframe 2
];
},
// keyframesGenerator_rewind() can be omitted in this case because
// the reversal of the forward keyframes is exactly equivalent.
// It is written below for demonstration purposes but commented out.
// -----------------------------------------------------------------------
// keyframesGenerator_rewind: () => {
// // return Keyframes (Keyframe[])
// return [
// {}, // Keyframe 1
// {scale: initialScale, opacity: 0} // Keyframe 2
// ];
// },
};
}
},
},
additionalMotionEffectBank: {
// -----------------------------------------------------------------
// ----------------------------EXAMPLE 2----------------------------
// -----------------------------------------------------------------
// Let us pretend you made this preset animation effect for moving an element rightward.
// For this animation, you wrote the forward keyframes generator and then
// checked to see if the desired rewinding effect could be achieved by just reusing
// keyframesGenerator_play() and reversing the result. You realize that this effect is NOT
// a candidate for that shortcut, so you write backwardKeyframesEffect.
translateRight: {
buildFrameGenerators(numPixels: number) {
// a helper function you wrote that will exist within a closure scoped to buildFrameGenerators()
const createTranslationString = () => {
if (numPixels <= 0) { throw RangeError(`Number of pixels must exceed 0.`) }
const translationString = `${numPixels}px`;
return translationString;
}
// return EffectFrameGeneratorSet
return {
keyframesGenerator_play: () => {
// return Keyframes (Keyframe[])
return [
{translate: createTranslationString()} // Keyframe
];
},
// keyframesGenerator_rewind() must be specified because reversing the keyframes produced
// by keyframesGenerator_play() would not have the intended effect (because of
// {composite: accumulate}, trying to simply use the reversal of
// {translate: createTranslationString()} from keyframesGenerator_play() would actually
// cause the target element to jump an additional numPixels pixels to the right
// before sliding left, which is not the intended rewinding effect).
keyframesGenerator_rewind: () => {
// return Keyframes (Keyframe[])
return [
{translate: '-'+createTranslationString()}, // Keyframe
];
},
};
},
immutableConfig: {
// this means that the translation is added onto the element's position
// instead of replacing it
composite: 'accumulate',
},
howOftenBuildGenerators: 'on-first-play-only',
},
}
});
const element = document.querySelector('.some-element');
(async () => {
const ent = clipFactories.Entrance(element, 'zoomIn', [0.2]);
await ent.play();
// ↑ keyframesGenerator_play() will run and produce the Keyframe array
// [{scale: initialScale, opacity: 0}, {scale: 1, opacity: 1}].
// That Keyframe array is used for the animation effect as the clip plays forward.
await ent.rewind();
// ↑ Since keyframesGenerator_rewind() was not set, the clip will run keyframesGenerator_play()
// again and just use its effect in reverse when rewinding (which would be exactly equivalent
// to specifying keyframesGenerator_rewind() and having it return
// [{}, {scale: initialScale, opacity: 0}]).
// In other words, keyframesGenerator_play() will run again to produce the Keyframe array
// [{scale: initialScale, opacity: 0}, {}], then
// the Keyframe array is used for the animation effect but set to go in reverse,
// and the effect is used as the clip rewinds.
const mot = clipFactories.Motion(element, 'translateRight', [756]);
await mot.play();
// ↑ keyframesGenerator_play() will run and produce the Keyframes array [{translate: '756px'}].
// That Keyframe array is used for the animation effect as the clip plays.
await mot.rewind();
// ↑ backwardFramesGenerator() will run and produce the Keyframe array [{translate: '-756px'}].
// That Keyframe array is used for the animation effect as the clip rewinds.
})();
OptionalkeyframesPerforms any necessary operations/computations and then returns keyframes (Keyframes).
Keyframes, either in the form of a PropertyIndexedKeyframes object or—more commonly—an array of Keyframe objects.
const clipFactories = webchalk.createAnimationClipFactories({
additionalEntranceEffectBank: {
// -----------------------------------------------------------------
// ----------------------------EXAMPLE 1----------------------------
// -----------------------------------------------------------------
// Let us pretend you made this preset entrance animation effect named 'zoomIn'.
// For this animation, you wrote the forward keyframes generator and
// then verified that the desired rewinding effect is exactly equivalent
// to playing the keyframes produced by keyframesGenerator_play() in reverse,
// so you omit keyframesGenerator_rewind.
zoomIn: {
buildFrameGenerators(initialScale: number) {
// return EffectFrameGeneratorSet
return {
keyframesGenerator_play: () => {
console.log('About to return keyframes!');
// return Keyframes (Keyframe[])
return [
{scale: initialScale, opacity: 0}, // Keyframe 1
{} // Keyframe 2
];
},
// keyframesGenerator_rewind() can be omitted in this case because
// the reversal of the forward keyframes is exactly equivalent.
// It is written below for demonstration purposes but commented out.
// -----------------------------------------------------------------------
// keyframesGenerator_rewind: () => {
// // return Keyframes (Keyframe[])
// return [
// {}, // Keyframe 1
// {scale: initialScale, opacity: 0} // Keyframe 2
// ];
// },
};
}
},
},
additionalMotionEffectBank: {
// -----------------------------------------------------------------
// ----------------------------EXAMPLE 2----------------------------
// -----------------------------------------------------------------
// Let us pretend you made this preset animation effect for moving an element rightward.
// For this animation, you wrote the forward keyframes generator and then
// checked to see if the desired rewinding effect could be achieved by just reusing
// keyframesGenerator_play() and reversing the result. You realize that this effect is NOT
// a candidate for that shortcut, so you write backwardKeyframesEffect.
translateRight: {
buildFrameGenerators(numPixels: number) {
// a helper function you wrote that will exist within a closure scoped to buildFrameGenerators()
const createTranslationString = () => {
if (numPixels <= 0) { throw RangeError(`Number of pixels must exceed 0.`) }
const translationString = `${numPixels}px`;
return translationString;
}
// return EffectFrameGeneratorSet
return {
keyframesGenerator_play: () => {
// return Keyframes (Keyframe[])
return [
{translate: createTranslationString()} // Keyframe
];
},
// keyframesGenerator_rewind() must be specified because reversing the keyframes produced
// by keyframesGenerator_play() would not have the intended effect (because of
// {composite: accumulate}, trying to simply use the reversal of
// {translate: createTranslationString()} from keyframesGenerator_play() would actually
// cause the target element to jump an additional numPixels pixels to the right
// before sliding left, which is not the intended rewinding effect).
keyframesGenerator_rewind: () => {
// return Keyframes (Keyframe[])
return [
{translate: '-'+createTranslationString()}, // Keyframe
];
},
};
},
immutableConfig: {
// this means that the translation is added onto the element's position
// instead of replacing it
composite: 'accumulate',
},
howOftenBuildGenerators: 'on-first-play-only',
},
}
});
const element = document.querySelector('.some-element');
(async () => {
const ent = clipFactories.Entrance(element, 'zoomIn', [0.2]);
await ent.play();
// ↑ keyframesGenerator_play() will run and produce the Keyframe array
// [{scale: initialScale, opacity: 0}, {scale: 1, opacity: 1}].
// That Keyframe array is used for the animation effect as the clip plays forward.
await ent.rewind();
// ↑ Since keyframesGenerator_rewind() was not set, the clip will run keyframesGenerator_play()
// again and just use its effect in reverse when rewinding (which would be exactly equivalent
// to specifying keyframesGenerator_rewind() and having it return
// [{}, {scale: initialScale, opacity: 0}]).
// In other words, keyframesGenerator_play() will run again to produce the Keyframe array
// [{scale: initialScale, opacity: 0}, {}], then
// the Keyframe array is used for the animation effect but set to go in reverse,
// and the effect is used as the clip rewinds.
const mot = clipFactories.Motion(element, 'translateRight', [756]);
await mot.play();
// ↑ keyframesGenerator_play() will run and produce the Keyframes array [{translate: '756px'}].
// That Keyframe array is used for the animation effect as the clip plays.
await mot.rewind();
// ↑ backwardFramesGenerator() will run and produce the Keyframe array [{translate: '-756px'}].
// That Keyframe array is used for the animation effect as the clip rewinds.
})();
OptionalmutatorPerforms any necessary operations/computations and then returns a function that will be run on every frame.
A function that presumably mutates the target element in some way (possibly with the help of AnimClip.computeTween) and will automatically be run on every frame. Since it will be run on every frame, it will create the illusion of a smooth animation.
const clipFactories = webchalk.createAnimationClipFactories({
additionalMotionEffectBank: {
// a preset animation effect for scrolling to a specific point on the page.
scrollTo: {
buildFrameGenerators(yPosition: number) {
const initialPosition = this.domElem.scrollTop;
// return EffectFrameGeneratorSet
return {
// The mutation is to use the scrollTo() method on the element.
// Thanks to computeTween(), there will be a smooth scroll
// from initialPosition to yPosition
mutatorGenerator_play: () => {
// return Mutator
return () => {
this.domElem.scrollTo({
top: this.computeTween(initialPosition, yPosition),
behavior: 'instant'
});
};
},
// The forward mutation loop is not invertible because reversing it requires
// re-computing the element's scroll position at the time of rewinding
// (which may have since changed for any number of reasons, including user
// scrolling, size changes, etc.). So we must define mutatorGenerator_rewind()
// to do exactly that.
mutatorGenerator_rewind: () => {
// return Mutator
return () => {
const currentPosition = this.domElem.scrollTop;
this.domElem.scrollTo({
top: this.computeTween(currentPosition, initialPosition),
behavior: 'instant'
});
};
},
};
}
},
}
});
const element = document.querySelector('.some-element');
const mot = clipFactories.Motion(element, 'scrollTo', [1020]);
mot.play().then(mot.rewind);
OptionalmutatorPerforms any necessary operations/computations and then returns a function that will be run on every frame.
A function that presumably mutates the target element in some way (possibly with the help of AnimClip.computeTween) and will automatically be run on every frame. Since it will be run on every frame, it will create the illusion of a smooth animation.
const clipFactories = webchalk.createAnimationClipFactories({
additionalMotionEffectBank: {
// a preset animation effect for scrolling to a specific point on the page.
scrollTo: {
buildFrameGenerators(yPosition: number) {
const initialPosition = this.domElem.scrollTop;
// return EffectFrameGeneratorSet
return {
// The mutation is to use the scrollTo() method on the element.
// Thanks to computeTween(), there will be a smooth scroll
// from initialPosition to yPosition
mutatorGenerator_play: () => {
// return Mutator
return () => {
this.domElem.scrollTo({
top: this.computeTween(initialPosition, yPosition),
behavior: 'instant'
});
};
},
// The forward mutation loop is not invertible because reversing it requires
// re-computing the element's scroll position at the time of rewinding
// (which may have since changed for any number of reasons, including user
// scrolling, size changes, etc.). So we must define mutatorGenerator_rewind()
// to do exactly that.
mutatorGenerator_rewind: () => {
// return Mutator
return () => {
const currentPosition = this.domElem.scrollTop;
this.domElem.scrollTo({
top: this.computeTween(currentPosition, initialPosition),
behavior: 'instant'
});
};
},
};
}
},
}
});
const element = document.querySelector('.some-element');
const mot = clipFactories.Motion(element, 'scrollTo', [1020]);
mot.play().then(mot.rewind);
Object containing a target element to animate and up to 4 callback functions that will be called to produce the effect for an co-animation within a clip. Contained in EffectFrameGeneratorSet returned by PresetEffectDefinition.buildFrameGenerators.
See
PresetEffectDefinition.buildFrameGenerators