質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

css animationが途中から適応されなくなる

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 309

score 7

前提・実現したいこと

HTML,CSS,Javascriptでwebページを作成しています。
仕様としてはスクロールするたびに表示する要素を変えるというものです。
keyframesで透明度を1→0にしてふんわり表示させる演出をしています。

発生している問題・エラーメッセージ

あいうえお→かきくけこ→さしすせそ→かきくけこ→さしすせそ
とスクロールすると、さしすせその時点でanimationが効かないです。

該当のソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <link rel="stylesheet" href="./css/style.css"> -->
</head>
<body>
    <div id="wrapper">
        <div class="box show" id="box-1"><span>あいうえお</span></div>
        <div class="box fade" id="box-2"><span>かきくけこ</span></div>
        <div class="box fade" id="box-3"><span>さしすせそ</span></div>
        <div class="box fade" id="box-4"><span>たちつてと</span></div>
        <div class="box fade" id="box-5"><span>なにぬねの</span></div>
    </div>
</body>

</html>
<!-- <script src="./js/scrollFunc.js"></script> -->

<style>
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
    }

    .box {
        width: 100vw;
        height: 100vh;
        position: relative;
    }

    span {
        position: absolute;
        font-size: 28px;
        top: 50%;
        left: 50%;
        transform: translateY(-50%) translateX(-50%);
    }

    #wrapper {
        width: 100vw;
        height: 100vh;
        overflow: hidden;
    }

    #box-1 {
        background-color: aliceblue;
    }

    #box-2 {
        background-color: antiquewhite;
    }

    #box-3 {
        background-color: aqua;
    }

    #box-4 {
        background-color: aquamarine;
    }

    #box-5 {
        background-color: indianred;
    }

    .fade {
        display: none;
    }

    .fade span {
        animation: show 1s linear 0s;
        animation-fill-mode: forwards;
        animation-direction: reverse
    }

    .show {
        display: block;
    }

    .show span {
        animation: show 1s linear 0s;
        animation-fill-mode: forwards;
    }

    @keyframes show {
        from {
            opacity: 0;
        }

        to {
            opacity: 1;
        }
    }
</style>

<script>
    var vox1 = document.getElementById('box-1');
    var vox2 = document.getElementById('box-2');
    var vox3 = document.getElementById('box-3');
    var vox4 = document.getElementById('box-4');
    var vox5 = document.getElementById('box-5');

    //スクロール上下判別
    var count = 0;
    const wheel = ((flag = false, timerId = null) => event => {
        clearTimeout(timerId);
        timerId = setTimeout(() => flag = false, 100); // 1秒空いたらリセット
        if (flag) return;

        if (event.wheelDeltaY < 0 && count < 4) {
            count = count + 1;
        } else if (event.wheelDeltaY > 0 && count > 0) {
            count = count - 1;
        }
        flag = true;

        if (count == 0) {
            vox1.classList.remove('fade');
            vox1.classList.add('show');
            vox2.classList.remove('show');
            vox2.classList.add('fade');
        } else if (count == 1) {
            vox2.classList.remove('fade');
            vox2.classList.add('show');
            vox1.classList.remove('show');
            vox1.classList.add('fade');
        } else if (count == 2) {
            vox3.classList.remove('fade');
            vox3.classList.add('show');
            vox2.classList.remove('show');
            vox2.classList.add('fade');
        } else if (count == 3) {
            vox4.classList.remove('fade');
            vox4.classList.add('show');
            vox3.classList.remove('show');
            vox3.classList.add('fade');
        } else if (count == 4) {
            vox5.classList.remove('fade');
            vox5.classList.add('show');
            vox4.classList.remove('show');
            vox4.classList.add('fade');
        }
    })();
    window.addEventListener("wheel", wheel);
</script>

試したこと

上記

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

なかなか再現できませんでしたが、一度なにぬねのまでスクロールダウンして、その後、あいうえおまで戻ると、さしすせそでフェードが機能しない状態になりますね。

これはなにぬねのからあいうえおに移動する際に、.showがremoveされていないことが原因のようです。
前の方のように効率の良い書き方はありますので、とりあえず使えればよいという場合はそちらを利用したほうが良いと思います。勉強的な意味合いと考えて、現状を変更する対策としては以下。
1 .fadeを消さないこと。.fadeはフェードアニメーションするためのclassなので消さないほうが間違いが少ないです。表示非表示は.showのみで制御したほうがシンプルです。

  1. スクロールアップ時に前のDOMからも.showを取り除く。

修正コードは以下です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <link rel="stylesheet" href="./css/style.css"> -->
</head>
<body>
<div id="wrapper">
    <div class="box fade show" id="box-1"><span>あいうえお</span></div>
    <div class="box fade" id="box-2"><span>かきくけこ</span></div>
    <div class="box fade" id="box-3"><span>さしすせそ</span></div>
    <div class="box fade" id="box-4"><span>たちつてと</span></div>
    <div class="box fade" id="box-5"><span>なにぬねの</span></div>
</div>
</body>

</html>
<!-- <script src="./js/scrollFunc.js"></script> -->

<style>
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
    }

    .box {
        width: 100vw;
        height: 100vh;
        position: relative;
    }

    span {
        position: absolute;
        font-size: 28px;
        top: 50%;
        left: 50%;
        transform: translateY(-50%) translateX(-50%);
    }

    #wrapper {
        width: 100vw;
        height: 100vh;
        overflow: hidden;
    }

    #box-1 {
        background-color: aliceblue;
    }

    #box-2 {
        background-color: antiquewhite;
    }

    #box-3 {
        background-color: aqua;
    }

    #box-4 {
        background-color: aquamarine;
    }

    #box-5 {
        background-color: indianred;
    }

    .fade {
        display: none;
    }

    .fade span {
        animation: show 1s linear 0s;
        animation-fill-mode: forwards;
        animation-direction: reverse
    }

    .show {
        display: block;
    }

    .show span {
        animation: show 1s linear 0s;
        animation-fill-mode: forwards;
    }

    @keyframes show {
        from {
            opacity: 0;
        }

        to {
            opacity: 1;
        }
    }
</style>

<script>
    var vox1 = document.getElementById('box-1');
    var vox2 = document.getElementById('box-2');
    var vox3 = document.getElementById('box-3');
    var vox4 = document.getElementById('box-4');
    var vox5 = document.getElementById('box-5');

    //スクロール上下判別
    var count = 0;
    const wheel = ((flag = false, timerId = null) => event => {
        clearTimeout(timerId);
        timerId = setTimeout(() => flag = false, 100); // 1秒空いたらリセット
        if (flag) return;

        if (event.wheelDeltaY < 0 && count < 4) {
            count = count + 1;
        } else if (event.wheelDeltaY > 0 && count > 0) {
            count = count - 1;
        }
        flag = true;
        if (count == 0) {
            vox1.classList.add('show');
            vox2.classList.remove('show');
        } else if (count == 1) {
            vox2.classList.add('show');
            vox3.classList.remove('show');
            vox1.classList.remove('show');
        } else if (count == 2) {
            vox3.classList.add('show');
            vox4.classList.remove('show');
            vox2.classList.remove('show');
        } else if (count == 3) {
            vox4.classList.add('show');
            vox5.classList.remove('show');
            vox3.classList.remove('show');
        } else if (count == 4) {
            vox5.classList.add('show');
            vox4.classList.remove('show');
        }
    })();
    window.addEventListener("wheel", wheel);
</script>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

元コードのJavascriptがよく解らなかったので、自作。
html css も少し変えました。
参考までにどうぞ

html + css + Javascript

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        .box {
            width: 100vw;
            height: 100vh;
            position: relative;
            display:none;
        }

        span {
            position: absolute;
            font-size: 28px;
            top: 50%;
            left: 50%;
            transform: translateY(-50%) translateX(-50%);
        }

        #wrapper {
            width: 100vw;
            height: 100vh;
            overflow: hidden;
        }

        #box-1 {
            background-color: aliceblue;
        }

        #box-2 {
            background-color: antiquewhite;
        }

        #box-3 {
            background-color: aqua;
        }

        #box-4 {
            background-color: aquamarine;
        }

        #box-5 {
            background-color: indianred;
        }

        .fade span {
            animation: show 1s linear 0s;
            animation-fill-mode: forwards;
            animation-direction: reverse
        }

        .show {
            display: block;
        }

        .show span {
            animation: show 1s linear 0s;
            animation-fill-mode: forwards;
        }

        @keyframes show {
            from {
                opacity: 0;
            }

            to {
                opacity: 1;
            }
        }
    </style>
</head>

<body>
    <div id="wrapper">
        <div class="box show" id="box-1"><span>あいうえお</span></div>
        <div class="box" id="box-2"><span>かきくけこ</span></div>
        <div class="box" id="box-3"><span>さしすせそ</span></div>
        <div class="box" id="box-4"><span>たちつてと</span></div>
        <div class="box" id="box-5"><span>なにぬねの</span></div>
    </div>
    <script>
        const box = document.getElementsByClassName("box");
        let timer = null;
const boxLen = box.length;

        window.addEventListener("wheel",(e)=>{
                clearTimeout(timer);
                timer = setTimeout( () => {
                    if (e.deltaY > 0) changeBoxUp();
                    if (e.deltaY < 0) changeBoxDown();
                }, 300);
        });

        const changeBoxUp = () => {
            for(let i = 0; i < boxLen; i++){
                if(i == boxLen - 1) {
                    box[i].classList.remove("show");
                    box[0].classList.add("show")
                } else if(box[i].classList.contains("show")) {
                    box[i].classList.remove("show");
                    box[i + 1].classList.add("show");
                    break;
                }
            }
        }

        const changeBoxDown = () => {

            for(let i = 0; i < boxLen; i++){
                if(i == 0 && box[i].classList.contains("show")) {
                    box[0].classList.remove("show");
                    box[boxLen - 1].classList.add("show");
                    break;
                } else if(box[i].classList.contains("show")){
                    box[i].classList.remove("show");
                    box[i - 1].classList.add("show");
                    break;
                }
            }
        }



    </script>
</body>

</html>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る