3
\$\begingroup\$

Depending on the width of the screen the JavaScript animates a node and then loops another animation.

I'm trying to understand DRY but my JavaScript skills aren't quite up to scratch to get this code as optimised as possible. I'm also wanting to implement $(window).resize(function() { }); to detect this change without a refresh. Is using constants the best way to optimise this code? If so, how would this be achieved?

jsFiddle

'use strict';

/*jslint browser: true*/
/*global $, jQuery*/

/*
--------------------------------------------------------
VARIABLES
--------------------------------------------------------
*/

var width       = $(window).width(),        // window width
    down_dur,
    left_dur,
    up_dur,
    right_dur;

/*
--------------------------------------------------------
FUNCTION CODE TO BE EXECUTED
--------------------------------------------------------
*/

function animate_node(down, down_dur, left, left_dur, up, up_dur, right, right_dur) {

    down        = down  + 'px';
    left        = left  + 'px';
    up          = up    + 'px';
    right       = right + 'px';

    $('.node')
        .animate({top: down},
            { duration: down_dur, easing : 'linear', queue: true })
        .animate({marginLeft: left},
            { duration: left_dur, easing : 'linear', queue: true })
        .animate({top: up},
            { duration: up_dur, easing : 'linear', queue: true })
        .animate({marginLeft: right},
            { duration: right_dur, easing : 'linear', queue: true });
}

/*
--------------------------------------------------------
CALL THE FUNCTIONS
--------------------------------------------------------
*/

// fire the following when the dom is ready
$(function () {

    if (width > 840) {
        $('.node').each(function(i) {
            $(this).delay(1500 * (i + 1))
                .animate({top: '157px'},
                    { duration: 1000, easing : 'linear', queue: true })
                .animate({marginLeft: '264px'},
                    { duration: 1000, easing : 'linear', queue: true });
        });
        animate_node(425, 2000, -284, 2000, 157, 2000, 264, 2000);
        setInterval(function() {
            animate_node(425, 2000, -284, 2000, 157, 2000, 264, 2000);
        }, 2000);
    } else if (width < 840 && width > 600) {
        $('.node').each(function(i) {
            $(this).delay(1500 * (i + 1))
                .animate({top: '165px'},
                    { duration: 1000, easing : 'linear', queue: true })
                .animate({marginLeft: '179px'},
                    { duration: 1000, easing : 'linear', queue: true });
        });
        animate_node(490, 2000, -199, 2000, 165, 2000, 179, 2000);
        setInterval(function() {
            animate_node(490, 2000, -199, 2000, 165, 2000, 179, 2000);
        }, 2000);
    } else if ((!(document.documentElement.hasOwnProperty('ontouchstart'))) &&
            width < 600) {
        $('.node').each(function(i) {
            $(this).delay(1833.333 * (i + 1));
        });
        animate_node(1095, 5000, 102, 500, 165, 5000, -9, 500);
        setInterval(function() {
            animate_node(1095, 5000, 102, 500, 165, 5000, -9, 500);
        }, 2000);
    }

});
\$\endgroup\$
  • \$\begingroup\$ Probably not because those constants may become incorrect (besides top and left which will be 0) when the window resizes \$\endgroup\$ – megawac Jan 15 '14 at 12:53
3
\$\begingroup\$

I would move all positions and other configuration to a simpleObject which contains a condition which is checked to determine if the configuration should be used for the current screen dimensions:

  • Remove unneeded variables
  • Added functions to remove duplication
  • Moved positions to animationConfig so logic and configuration is separated

I made a assumption in the code which is that the path is always a square, so up, down, left and right duration are replaced with a horizontal and vertical duration

jsfiddle: http://jsfiddle.net/EJF9q/1/

'use strict';

function animate_node(down, down_dur, left, left_dur, up, up_dur, right, right_dur) {

    function animate_cfg(duration) {
        return { duration: duration, easing : 'linear', queue: true };
    }

    down    += 'px';
    left    += 'px';
    up      += 'px';
    right   += 'px';

    $('.node')
        .animate({top: down},           animate_cfg(down_dur))
        .animate({marginLeft: left},    animate_cfg(left_dur))
        .animate({top: up},             animate_cfg(up_dur))
        .animate({marginLeft: right},   animate_cfg(right_dur));
}

function animate_config(config) {
    animate_node(
        config.down,
        config.vertical_dur,
        config.left,
        config.horizontal_dur,
        config.up,
        config.vertical_dur,
        config.right,
        config.horizontal_dur);
}

// OnReady
$(function () {

    var animationConfigs = [
        {
            startTop: 157,
            delay: 1500,
            down: 425,
            left: -284,
            up: 157,
            right: 264,
            vertical_dur: 2000,
            horizontal_dur: 2000,
            conditions: function() {
                return $(window).width() > 840;
            }
        },
        {
            delay: 1500,
            down: 490,
            left: -199,
            up: 165,
            right: 179,
            vertical_dur: 2000,
            horizontal_dur: 2000,
            conditions: function() {
                return $(window).width() < 840 && $(window).width() > 600;
            }
        },
        // Etc...
    ];

    for (var i in animationConfigs) {
        var animationCfg = animationConfigs[i];
        if (animationCfg.conditions()) {
            $('.node').each(function(i) {
                $(this).delay(1500 * (i + 1))
                    .animate({ top: animationCfg.up + 'px' },
                        { duration: 1000, easing : 'linear', queue: true })
                    .animate({marginLeft: animationCfg.right + 'px'},
                        { duration: 1000, easing : 'linear', queue: true });
            });
            animate_config(animationCfg);
            setInterval(function() {
                animate_config(animationCfg);
            }, 2000);
            break;
        }
    }
});
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.