Reveal.js中片段更改的自定义事件

时间:2018-07-20 11:45:33

标签: javascript reveal.js

以编程方式将片段添加到Reveal.js中的幻灯片上的正确方法是什么?我在幻灯片上有一个JavaScript窗口小部件,该窗口小部件可以经历5种状态,我想通过片段过渡来进行遍历。

我尝试使用虚拟片段实现类似的效果,如下面的代表性示例所示。目的是在片段更改时更改图像的src。但是,该示例存在问题。通过多次按 previous 接近幻灯片时,幻灯片应从其最后的片段状态开始。但是,在示例中,图像src从状态1开始,并且不知道如何在其他上一个步骤上进一步返回。

任何指针将不胜感激!

<img src="img1.png" id="my-image">
<span class="fragment update-img-src" data-target="my-image" data-src="img2.svg"></span>

<script>
Reveal.addEventListener('fragmentshown', function(event) {
    if (event.fragment.classList.contains('update-img-src')) {
        // Find the target image by ID
        var target = document.getElementById(event.fragment.dataset.target);
        // Keep a stack of previously shown images, so we can always revert back on 'fragmenthidden'
        if (target.dataset.stack == null) {
            target.dataset.stack = JSON.stringify([target.getAttribute('src')]);
        }
        target.dataset.stack = JSON.stringify([event.fragment.dataset.src, ...JSON.parse(target.dataset.stack)]);
        // Update the image
        target.setAttribute('src', event.fragment.dataset.src);
    }
});
Reveal.addEventListener('fragmenthidden', function(event) {
    if (event.fragment.classList.contains('update-img-src')) {
        // Return to the previously shown image.
        // Remove the top from the history stack
        var target = document.getElementById(event.fragment.dataset.target);
        if (target.dataset.stack == null) {
            console.log('Trying to hide', event.fragment.dataset.src, 'but there is no stack.');
        } else {
            var [_, ...tail] = JSON.parse(target.dataset.stack);
            target.dataset.stack = JSON.stringify(tail);
            // Set the image source to the previous value
            target.setAttribute('src', tail[0]);
        }
    }
});
</script>

1 个答案:

答案 0 :(得分:0)

这是我整理的一个骇人听闻的解决方案。它允许您使用回调函数在幻灯片上注册任意数量的片段。

function registerFakeFragments(slide, fragmentIndices, stateChangeHandler) {
    const identifier = `fake-${Math.round(1000000000*Math.random())}`;
    let i = 1;
    for (let fragmentIndex of fragmentIndices) {
        const span = document.createElement('span');
        span.dataset.target = identifier;
        span.classList.add('fragment');
        span.classList.add('fake-fragment');
        span.setAttribute('data-fragment-index', JSON.stringify(fragmentIndex));
        span.dataset.stateIndex = JSON.stringify(i);
        slide.appendChild(span);
        ++i;
    }
    let currentState = null; // last reported state
    const listener = () => {
        const currentSlide = Reveal.getCurrentSlide();
        if (currentSlide && currentSlide === slide) {
            // Find the latest visible state
            let state = 0;
            currentSlide.querySelectorAll(`.fake-fragment.visible[data-target=${identifier}]`).forEach(f => {
                const index = JSON.parse(f.dataset.stateIndex);
                if (index > state) {
                    state = index;
                }
            });
            // If the state changed, call the handler.
            if (state != currentState) {
                stateChangeHandler(state);
                currentState = state;
            }
        }
    };
    Reveal.addEventListener('fragmentshown', listener);
    Reveal.addEventListener('fragmenthidden', listener);
    Reveal.addEventListener('slidechanged', listener);
}