jq-scroll-anim

jQuery plugin for define animations whose reproduction depends on the position of the vertical scroll

Usage no npm install needed!

<script type="module">
  import jqScrollAnim from 'https://cdn.skypack.dev/jq-scroll-anim';
</script>

README

jqScrollAnim

Trigger animations with the vertical scroll

jqScrollAnim is a jQuery plugin that allows to define animations whose reproduction depends on the position of the vertical scroll.

This plugin was inspired by the site SlaveryFootpring.org, whose content appear and disappear as response for the vertical scroll movement.

Demos

Sample: http://jfmdev.github.io/jqScrollAnim/demos.html

How to use

Step 1: Add references to the files of jQuery and jqScrollAnim in the header section of the HTML document.

    <script type="text/javascript" src="jquery-1.11.1.min.js"></script>
    <script type="text/javascript" src="jqscrollanim.js"></script>

Step 2: Select the element (or elements) that you want to animate, and invoke the method jqScrollAnim().

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {type:'fade'}		
        });
    });

Live demo

Tutorial

Triggers

While standard animations are triggered by time, the animations in jqScrollAnim are triggered by the vertical scroll's position, so the animations are reproduced when the vertical scroll is being moved.

Reproduction

When creating an animation with jqScrollAnim, the parameter rep, whose main properties are start and end, allow to define when the animation must start and when it must finish.

Every time that the vertical scroll is moved, the plugin calculates the distances (in pixels) between the animated elements and the screen's margins. So when the distance of an element is equal to rep.start the animation starts to reproduce, and when the distance is equal to rep.end the animations ends.

For example, in the code:

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {type:'fade'}		
        });
    });

Live demo

The element is going to be invisible until the distance between him and the lower margin is 0, from that point the element is going to become less transparent until the distance is equal to 200, when is going to become opaque. So if the distance is 100, the element is going to be 50% transparent, and if the distance is 150, the element is going to be 25% transparent.

Margins

By default, the distances are always calculated between the bottom of the screen and the upper side of the element (since normally, in a website, one must scroll down to continue). However, this can be changed by using the ref property, whose possible values are:

  • "upper-bottom": the distance is calculated between the bottom of the screen and the upper side of the element.
  • "base-bottom": the distance is calculated between the bottom of the screen and the lower side of the element.
  • "upper-top": the distance is calculated between the top side of the screen and the upper side of the element.
  • "base-top": the distance is calculated between the top side of the screen and the lower side of the element.

For example:

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200, ref:'top-bottom'},
            animation: {type:'fade'}		
        });
        jQuery("#another_element").jqScrollAnim({
            rep: {start: 0, end: 200, ref:'base-bottom'},
            animation: {type:'fade'}		
        });
    });

Live demo

Keep in mind that when using "upper-top" and "base-top", the values for start and end normally are going to be negative, otherwise the animation is going to start playing after the element has started to be outside the visible region.

For example:

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: -200, end: 0, ref:'upper-top'},
            animation: {type:'fade'}		
        });
    });

Live demo

Relative distances

Since different visitors normally have different screen resolutions, you can also define the triggers by using percentage values. This is done by setting the property unit (whose default value is "px") to "%".

So, in the following example:

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0.25, end: 0.5, unit: "%"},
            animation: {type:'fade'}		
        });
    });

Live demo

The element is going to be invisible until the distance between him and lower margin is equal to a quarter of the screen size, and is going to become opaque when the distance is equal to half the screen size.

Rewind

After reproducing the animation, it is also possible to define a trigger to 'rewind' the animation. This is done by using the parameter rew, which has the same properties than rep but with the difference that his default value for ref is "base-bottom" (instead of "top-upper").

For example:

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 50, end: 250},
            rew: {start: -250, end: -50},
            animation: {type:'fade'}		
        });
    });

Live demo

In this case, the element is going to be invisible until the distance between his top side and the bottom of the screen is 50, then is going to become more opaque until the distance is 250, after that is going to be fully opaque until the distance between the element's bottom and the top side of the screen is 250, when is going to become less opaque until the distance is 50, and after that is going to become invisible again.

Animations

The effect of an animation is defined by the animation parameter, an object that accept the properties type, property, start, end, unit and action.

The type property is the only property that is mandatory, since it defines the type of data that is going to be processed during the animation. It can hold the values: 'integer', 'number', 'color', 'fade', 'move-left', 'move-right' and 'custom'.

The value of property indicates which CSS property is going to be modified by the animation; the properties start and end define the initial and final values of the CSS property; while unit indicates which unit must be used (such as '%', 'px' or 'pt').

Finally, the action property is only used when type has the value 'custom'.

Basics types

The main animation types are "integer", "number", "color" and "sequence", which indicates that kind of data is hold by the CSS property that is modified by the animation. When using these types, the property property is required, as well as either start or end (at least one of them must be defined). And depending of the CSS property used, the property unit may be required also.

Note that if the values start or end are not defined, by default they are going to be initialized with the initial value of the animated element. An exception to this is the type "sequence", in which start is never used and end must always be defined.

Example:

    jQuery(document).ready(function() {
        // Animation for 'element_1'.
        jQuery("#element_1").jqScrollAnim({
            rep:  {start: 0, end: 200},
            animation: {type:'number', property:'opacity', start:0}		
        });
        
        // Animation for 'element_2'.
        jQuery("#element_2").jqScrollAnim({
            rep:  {start: 0, end: 200},
            animation: {type:'integer', property:'font-size', end:20, unit:'pt'}		
        });
        
        // Animation for 'element_3'.
        jQuery("#element_3").jqScrollAnim({
            rep:  {start: 0, end: 200},
            animation: {type:'color', property:'background-color', start:[255,0,0], end:[0,255,0]}		
        });
        
        // Animation for 'element_4'.
        jQuery("#element_4").jqScrollAnim({
            rep:  {start: 0, end: 200},
            animation: {type:'sequence', property:'background-color', end:['white', 'red', 'green', 'blue']}
        });
    });

Live demo

In this example, the first animation has the type "number" and is going to change the opacity of the element from 0 to the current opacity value (normally 1). Since the CSS property "opacity" has no unit, the unit property is not required.

The second animation has the type "integer" and is going to change the font size from his current size to 20. The unit property was defined since, in CSS, the "font-size" property requires an unit.

The third animation has the type "color" and is going to change the background color from red to green. When using the type "color", the property unit is never used.

The fourth animation has the type "sequence" and is going to change sequentially the background color four times. When using the type "sequence", the property start is never used and the property end must always be defined as an array of string values.

Synonym types

The types "fade", "move-left" and "move-out" are, in fact, synonyms for the basic types but that have different default values for the other properties.

The type "fade" is a synonym for "number" that defines that the default value for property is "opacity", for start is 0 and for end is 1. As consequence, {type: 'fade'} is equivalent to {type: 'integer', property: 'opacity', start:0, end:1}

Live demo

The types "move-left" and "move-right" are synonyms for "integer" that defines that the default value for property is "left", for unit is "px" and for end is "out-left" or "out-right" (these two are special values that are mapped, respectively, to the element width or to the windows width). As consequence, {type: 'move-left'} is equivalent to {type: 'integer', property:'left', end:'out-left'} and {type: 'move-right'} is equivalent to {type: 'integer', property:'left', end:'out-right'}

Live demo

In a side note, when doing movement animations, do not forget that, in most cases, the animation is not going to work unless the element has defined the CSS property "position".

Custom

In case that some particular effect can not be obtained by using any of the previous types, the type "custom" can be used. When using this type, the property "action" must be filled with a function which is going to be invoked every time that the vertical scroll is moved.

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {
                type: 'custom',
                action: function(target, settings, progress) {
                        target.css('padding', parseInt(progress*20 ,10) + 'px');
                    }
                }
        });
    });

Live demo

The action's function receives three parameters:

  • target is a jQuery object for the element which must be modified.
  • settings contains the value of the triggers (rep and rew).
  • progress is a number between 0 and 1 indicating the progress of the animation.

Advanced animations

Vertical movements

One limitation of using the position of the element (that must be animated) to calculate the distance to the margins, is that the element can not be moved up or down, since that would cause unexpected results when calculating again the distance to the margins.

The solution to this is to use an "stake", i.e. to use the position of another element (that is not going to be moved) to calculate the distances. This can be done by using the stake property, which holds a CSS selector that identifies the motionless element.

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {type: 'integer', property:'top', end:0, start:350},
            stake: "#another_element"
        });
    });

Live demo

Synchronized animations

The stake property can also be used for do synchronized animations, i.e. to animate simultaneously several element that are at different positions.

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {type: 'integer', property:'width', end:10, start:100},
            stake: "#stake_element"
        });
        
        jQuery("#another_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {type: 'integer', property:'width', end:10, start:100},
            stake: "#stake_element"
        });
    });

Live demo

Sequential animations

In order to do sequential animations, you can add several animations to the same element (or to different elements with the same stake) and configure their trigger points to be consecutive.

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 200},
            animation: {type: 'color', property:'background-color', end:[128,128,255]}
        });
        
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 200, end: 400},
            animation: {type: 'color', property:'background-color', start:[128,128,255], end:[128,255,128]}
        });
    });

Live demo

Concurrent animations

In order to define several animations that acts at the same time over the same element, you can individually define each of these animations and use the same trigger points, but a more efficient way would be to use the animations property, which accepts an array, instead of animation.

    jQuery(document).ready(function() {
        jQuery("#some_element").jqScrollAnim({
            rep: {start: 0, end: 400},
            animations: [
                {type: 'color', property:'background-color', end:[128,0,0]},
                {type: 'integer', property:'font-size', end:20, unit:'pt'},
                {type: 'integer', property:'border', end:5, unit:'px'}
            ]
        });
    });

Live demo