如何将requestAnimationFrame与Promise一起使用

问题描述 投票:0回答:3

我想将requestAnimationFrame与Promise一起使用,所以我可以这样使用它

opacityToggle("layername",0).then(i=>"do some stuff after animation ends")

,但不知道该怎么做。这是我的代码:

function opacityToggle(layerName, opacity) {

    if (!layerName) return;
    var requestID;
    var s = 0;
   
    return animate().then(i => i)

    function animate() {
        requestID = requestAnimationFrame(animate);
        if (s < 1) {
            s += 0.01
            s = +s.toFixed(2)
            console.log('s', layerName, s, opacity);
            map.setPaintProperty(layerName, 'fill-opacity', s);
        } else {
            cancelAnimationFrame(requestID);
            return new Promise(resolve => resolve)
        }
    }
}

javascript es6-promise
3个回答
5
投票

虽然 @Terry 有一个简单的解决方案,将所有内容都包装在 Promise 构造函数中,但如果您仅 Promise

requestAnimationFrame
调用本身,那么您将获得 Promise 的真正力量:

async function opacityToggle(layerName, opacity) { /*
^^^^^ */
    if (!layerName) return;

    var s = 0;
    while (s < 1) {
//  ^^^^^
        s += 0.01
        s = +s.toFixed(2)
        console.log('s', layerName, s, opacity);
        map.setPaintProperty(layerName, 'fill-opacity', s);

        await new Promise(resolve => {
//      ^^^^^
            requestAnimationFrame(resolve);
//          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        });
    }
}

如果你不能使用

async
/
await
和/或想用递归方法来做到这一点,那就是

function opacityToggle(layerName, opacity) {
    if (!layerName) return Promise.resolve();

    var s = 0;
    return animate();

    function animate() {
        if (s < 1) {
            s += 0.01
            s = +s.toFixed(2)
            console.log('s', layerName, s, opacity);
            map.setPaintProperty(layerName, 'fill-opacity', s);
            return new Promise(resolve => {
//          ^^^^^^
                requestAnimationFrame(resolve);
            }).then(animate);
//            ^^^^^^^^^^^^^^
        } else {
            return Promise.resolve();
        }
    }
}

1
投票

您的

opacityToggle
函数的 return 语句有点过于复杂。您只需返回 Promise 并将所有 RAF 逻辑封装在其中即可。这应该足够了:

function opacityToggle(layerName, opacity) {

    if (!layerName) return;
    var requestID;
    var s = 0;

    return new Promise(resolve => {
        // Animation steps
        function animate() {
            if (s < 1) {
                s += 0.01
                s = +s.toFixed(2)
                console.log('s', layerName, s, opacity);
                map.setPaintProperty(layerName, 'fill-opacity', s);

                requestID = requestAnimationFrame(animate);
            } else {
                // If animation is complete, then we resolve the promise
                cancelAnimationFrame(requestID);
                resolve();
            }
        }

        // Start animation
        requestID = requestAnimationFrame(animate);
    });
}

您的问题并不清楚您想要以什么价值来解决承诺。如果您愿意,可以简单地将其提供为

resolve(yourResolvedValueHere)


0
投票

这是一个有用的技巧,您可以尝试一下。

async function sleep() {
    return new Promise(requestAnimationFrame);
}
    
async function loop() {
    do {
    // render things here
    // you can also await stuff in here
    await sleep();
    } while (1);
}

loop();
© www.soinside.com 2019 - 2024. All rights reserved.