简体   繁体   中英

How to clear interval inside a function calling itself javascript

I need to clear interval of function in this example

$.fn.bounce = function(options) {

    var settings = $.extend({
        speed: 10
    }, options);

    return $(this).each(function() {

        var $this = $(this),
            $parent = $this.parent(),
            height = $parent.height(),
            width = $parent.width(),
            top = Math.floor(Math.random() * (height / 2)) + height / 4,
            left = Math.floor(Math.random() * (width / 2)) + width / 4,
            vectorX = settings.speed * (Math.random() > 0.5 ? 1 : -1),
            vectorY = settings.speed * (Math.random() > 0.5 ? 1 : -1);

        // place initialy in a random location
        $this.css({
            'top': top,
            'left': left
        }).data('vector', {
            'x': vectorX,
            'y': vectorY
        });

        var move = function($e) {

            var offset = $e.offset(),
                width = $e.width(),
                height = $e.height(),
                vector = $e.data('vector'),
                $parent = $e.parent();

            if (offset.left <= 0 && vector.x < 0) {
                vector.x = -1 * vector.x;
            }
            if ((offset.left + width) >= $parent.width()) {
                vector.x = -1 * vector.x;
            }
            if (offset.top <= 0 && vector.y < 0) {
                vector.y = -1 * vector.y;
            }
            if ((offset.top + height) >= $parent.height()) {
                vector.y = -1 * vector.y;
            }

            $e.css({
                'top': offset.top + vector.y + 'px',
                'left': offset.left + vector.x + 'px'
            }).data('vector', {
                'x': vector.x,
                'y': vector.y
            });

            setTimeout(function() {
                move($e);
            }, 50);

        };

        move($this);
    });

};

$(function() {
    $('#wrapper li').bounce({
        'speed': 7
    });
});

So whenever I need I start the animating circle and when I don't want I can stop. So in the above code you can see move($this); is getting called in interval what I need to stop or clear the interval so the circle stop animating. and when again I need I can just click the button and it again start animation.

I divided your code in bounce function into three section:

  1. One for initialization where the element took their start positions.
  2. Another for the logic of animation (with the start and stop added)
  3. The last one is for the movement (the same function move but insetead of define it inside each (not good because it will get redifined for every element), I defined it outside the each ).

The code contain tons of comments. If something is still unclear post a comment bellow.

 $.fn.bounce = function(options) { var settings = $.extend({ speed: 10 }, options); // Keep a reference to this to use when we are inside bounded functions (where this is something different) var that = this; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// LOGIC FOR INITIALIZATION /////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // function init to initialize the elements. function init(){ $(that).each(function() { var $this = $(this), $parent = $this.parent(), height = $parent.height(), width = $parent.width(), top = Math.floor(Math.random() * (height / 2)) + height / 4, left = Math.floor(Math.random() * (width / 2)) + width / 4, vectorX = settings.speed * (Math.random() > 0.5 ? 1 : -1), vectorY = settings.speed * (Math.random() > 0.5 ? 1 : -1); // place initialy in a random location $this.css({ 'top': top, 'left': left }).data('vector', { 'x': vectorX, 'y': vectorY }); }); } // call it right away (initialize) before starting anything else init(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// LOGIC FOR ANIMATION /////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // the boolean that will stop the animation var keepGoing = false; // If the selector for the start button is specified if(settings.start){ // attach animate to its click event listener $(settings.start).on("click", animate); } else // no button is provided then start automatically animate(); // If the selector for the stop button is specified if(settings.stop){ // attach stop to its click event listener $(settings.stop).on("click", stop); } // the function that will start the animation function animate(){ // If we are not already animating if(!keepGoing){ keepGoing = true; // call move on all the elements to start the magic. // we use 'that' instead of 'this' here because 'this' is the button that have been clicked (see the event listener above=. $(that).each(function() { move($(this)); }); } } // the function that will stop the animation ... function stop(){ // ... by simply set keepGoing to false keepGoing = false; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// LOGIC FOR MOVEMENT /////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // the move function responsible for moving the elements function move($e) { var offset = $e.offset(), width = $e.width(), height = $e.height(), vector = $e.data('vector'), $parent = $e.parent(); if (offset.left <= 0 && vector.x < 0) { vector.x = -1 * vector.x; } if ((offset.left + width) >= $parent.width()) { vector.x = -1 * vector.x; } if (offset.top <= 0 && vector.y < 0) { vector.y = -1 * vector.y; } if ((offset.top + height) >= $parent.height()) { vector.y = -1 * vector.y; } $e.css({ 'top': offset.top + vector.y + 'px', 'left': offset.left + vector.x + 'px' }).data('vector', { 'x': vector.x, 'y': vector.y }); // if keep going, ... you know, keep going. if(keepGoing){ setTimeout(function() { move($e); }, 50); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } // the options can have the 'start' and 'stop' selector optionally. $(function() { $('#wrapper li').bounce({ 'speed': 7, 'start': '#startAnimation', // selector of the element that when clicked the animation will start. If not provided the animation will start automatically 'stop' : '#stopAnimation' // selector of the element that when clicked the animation will stop (pause). If not provided the animation will go for ever }); }); 
 body, * { padding: 0 !important; margin: 0: } #wrapper { width:500px; height: 500px; border: 1px solid red; } li { position: absolute; width: 60px; height: 60px; -webkit-border-radius: 30px; -moz-border-radius: 30px; border-radius: 30px; background-color:#0FF; line-height: 60px; text-align:center; cursor:pointer; } button{ width: 100px; height: 30px; } 
 <script src='http://code.jquery.com/jquery-3.1.1.min.js'></script> <ul id="wrapper"> <button id="startAnimation">Start</button> <button id="stopAnimation">Stop</button> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> 

I think you want to be using setInterval for this problem. You can use clearInterval on the instance of setInterval you created to make it stop.

Why I think you should be using setInterval instead of setTimeout? Well because setInterval is meant for running functions in a certain time interval (which is what you want to do). Where as setTimeout is meant to delay a function call.

 // sample code var counter = 0; var example = setInterval(function(){ console.log(counter); if (counter == 10) { console.log("I'm out"); clearInterval(example); } counter++; }, 300); 

You can assign timeout function to a variable and use clearTimeout method. Like below:

var timer = setTimeout(function() {
            move($e);
        }, 50);

clearTimeout(timer);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM