简体   繁体   中英

Javascript: How to ensure that onClick events are only triggered once prior events have completed?

I've written code that colors points on a canvas when the user clicks them. Points are colored by way of a fade-in animation, so it takes a certain amount of time to color a given point. Problems occur if the user clicks a new point while a prior point is still being colored: anomalous colors are produced, fade-in animations continue indefinitely without stopping, etc.

I would like is to make it so that, when the user clicks on a point, any subsequent clicks are ignored until the function coloring that point has completed. Upon completion, the user should be able to click another point to color it (ie the onClick coloring functionality should be restored).

In searching for solutions to this problem, I mostly found code designed for events that are only executed once. However, this is not quite what I need. My user should be able to be able to trigger an arbitrary number of coloring events--I just don't want any of these events to ever happen concurrently, as it were. Thanks for any help!

You can use locking, like:

var block = false;
element.addEventListener("click", function () {
    if (block === true) {
        return;
    }
    block = true;
    doOperation("params", function () {
        block = false;
    });
});

function doOperation(input, callback) {
    setTimeout(callback, 1000);
}

This blocks clicks for about 1 second.

Commonly you'll use promises instead of the callback:

var block_promise = null;
element.addEventListener("click", function () {
    if (block_promise === null || block_promise.is_resolved() === false) {
        return;
    }
    block_promise = doOperation("params");
});

function doOperation(input, callback) {
    var promise = new Promise();
    setTimeout(function () {
        promise.resolve();
    }, 1000);
    return promise.promise();
}

Note that Promises are not (yet) natively supported in JavaScript. Use your favorite library.

If you have a way of setting a flag when painting is occurring, you could try this. Here I set a flag to true when painting starts and false when it is done. In the buttonClick() function, I immediately exit if painting is true.

<!DOCTYPE html>
<html>

<head>
<title>Button Test</title>
</head>

<body>
<script>
var painting = false;
var clicks = 0;

function buttonClick() {

    //if painting, immediately exit buttonClick
    if (painting)
        return;

    //display click count whenever we enter here
    clicks++;
    var obj = document.getElementById("clicks");
    obj.value=clicks;

    //simulate painting
    painting = true;
    document.getElementById("status").innerHTML = "painting in progress";
    setTimeout(function() { colorPoint()}, 10000 /* 10 seconds */ );

}

function colorPoint() {
    //simulated painting
    painting = false; //allows button to be clicked again
    document.getElementById("status").innerHTML = "painting done";
}

</script>

<button onclick="buttonClick()">Click me</button>
Button clicks: <input type="text" name="clicks" id="clicks">
<div id="status"> </div>

</body>
</html>

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