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

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

ただいまの
回答率

88.64%

html cssアニメーション @keyframes と javascript の複合についての質問

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 189

vfxl9827

score 8

html cssアニメーション @keyframes と javascript の複合についての質問

以下は矢印ワンクリックで数字の書かれた1コマ(400*400px)ずつがスライドするのですが,これをセレクトボックスと実行ボタンで選択した番号コマまで自動で移動する方法をご教示ください。

現状 >>> 0コマ目(初期状態)から4コマ目の移動には,1,2,3コマ目と途中4回(1回1秒×4回=4秒かけて移動)[送り]ボタンクリックする方式。

希望 >>> 各コマ数が書かれた[プルダウン]と[実行]ボタンを配置の上,0コマ目(初期状態)の状態からプルダウンで4コマ目へ移動という項目を選択,実行ボタンで1,2,3コマ目とアニメーションで通過しながら(通過時間1回1秒×4コマ=4秒間かけて)移動という方式にしたい。また再び別の番号の項目選択でそのコマ数まで移動

追加 回答をいただいた各アニメーション終了後に以下の拡大縮小アニメーションを追加するにはどうすればよいでしょうか。後片付けで大変申し訳ございません

  from {
    transform: scale(0.9,0.9);
  }
  to {
    transform: scale(1,1);

html

<div class="parent">
<span class="child" id="box">
<div style=" width:400px;height:400px; background-color: #999;">0</div>
<div style=" width:400px;height:400px; background-color: #555;">1</div>
<div style=" width:400px;height:400px; background-color: #999;">2</div>
<div style=" width:400px;height:400px; background-color: #555;">3</div>
<div style=" width:400px;height:400px; background-color: #999;">4</div>
<div style=" width:400px;height:400px; background-color: #555;">5</div>
<div style=" width:400px;height:400px; background-color: #999;">6</div>
<div style=" width:400px;height:400px; background-color: red;">7</div>
</span>
</div>


<input type="button" onclick="move(1);" value=" 送り " id="btn"/>
<input type="button" onclick="move(2);" value=" 戻し " id="btn"/>

CSS

div.parent {
    position: relative;
    width: 400px;
height: 400px;

    border: 1px solid #ddd;
    overflow: hidden;
}
span.child {
    position: absolute;
    width : 400px;
 height: 3200px;
    left: 0px;
top:0px;
    animation-duration: 1s;
    animation-iteration-count: 1;
animation-timing-function: linear;
    animation-fill-mode: forwards;
}

@keyframes moveDown {

    100% {
        transform:translateY(-400px);
    }
}
@keyframes moveUp {

 100% {
        transform:translateY(400px);
    }
}

JS

var x, y;   // box の座標

// 移動   1=上, 2=下
function move(direct) {

    const objBox = document.getElementById("box");
    const cssStyle = window.getComputedStyle(objBox);
    y = parseInt(cssStyle.top.match(/(.*)px/)[1]);

    let anim = '';
    switch (direct) {
        case 1: if (y >= -2400) { anim = 'moveDown'; } break;
        case 2: if (y <= -400) { anim = 'moveUp'; } break;
    }

    if (anim !== '') {
        objBox.style.animationName = anim;  // アニメ開始
        btnsDisabled(true); // ボタン無効化
    }
}
// animation 終了時の処理
document.addEventListener('animationend', () => {
    const objBox = document.getElementById("box");
    const cssStyle = window.getComputedStyle(objBox);
    const arr = cssStyle.transform.match(/\((.*)\)/)[1].split(",");     // 文字列 matrix(a, b, c, d, cx, cy) を分解
    y += parseInt(arr[5]);  // transform.y の値を加える

    objBox.style.transform = '';        // アニメした transform を消す
    objBox.style.top = y + 'px';
    objBox.style.animationName = '';    // animationName を消す。こうしないと、次回に同じ方向のアニメが効かない。

    btnsDisabled(false);    // ボタン有効化
});

// 矢印ボタンの有効化/無効化
function btnsDisabled(arg) {
    let btns = document.getElementsByTagName("input");
    for (let i = 0; i < btns.length; i++) {
        btns[i].disabled = arg;
    }
}


お手数をおかけしますが何卒よろしくお願い申し上げます。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • vfxl9827

    2020/10/05 18:57

    ご親切にありがとうございます。すみません。まだなれないものでして。また後ほど修正してお知らせしますのでよろしくお願いします。

    キャンセル

  • vfxl9827

    2020/10/05 22:13

    修正しました。ここからご教示お願い致します。

    キャンセル

  • vfxl9827

    2020/10/09 00:36

    **追加** 回答をいただいた各アニメーション終了後に以下の拡大縮小アニメーションを追加するにはどうすればよいでしょうか。後片付けで大変申し訳ございません
    ```@keyframes anime1 {
    from {
    transform: scale(0.9,0.9);
    }
    to {
    transform: scale(1,1);
    ```

    キャンセル

回答 1

checkベストアンサー

0

なるべく原型をとどめる方向で調整しました。
変更部分はコメント残すようにしてるけど、
ここまでできるのになぜ質問したのかが不思議?

<!DOCTYPE html>
<html lang="ja" >
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
<div class="parent">
<span class="child" id="box">
<div style=" width:400px;height:400px; background-color: #999;">0</div>
<div style=" width:400px;height:400px; background-color: #555;">1</div>
<div style=" width:400px;height:400px; background-color: #999;">2</div>
<div style=" width:400px;height:400px; background-color: #555;">3</div>
<div style=" width:400px;height:400px; background-color: #999;">4</div>
<div style=" width:400px;height:400px; background-color: #555;">5</div>
<div style=" width:400px;height:400px; background-color: #999;">6</div>
<div style=" width:400px;height:400px; background-color: red;">7</div>
</span>
</div>
<input type="button" onclick="move(1);" value=" 送り " id="btn1"/>
<input type="button" onclick="move(2);" value=" 戻し " id="btn2"/>
<select id="divno" onchange="selected();">
<option value="0" selected>0ページ</option>
<option value="1">1ページ</option>
<option value="2">2ページ</option>
<option value="3">3ページ</option>
<option value="4">4ページ</option>
<option value="5">5ページ</option>
<option value="6">6ページ</option>
<option value="7">7ページ</option>
</select>
</body>
</html>
div.parent {
    position: relative;
    width: 400px;
    height: 400px;
    border: 1px solid #ddd;
    overflow: hidden;
}
span.child {
    position: absolute;
    width : 400px;
    height: 3200px;
    left: 0px;
    top:0px;
    /* animation-duration: 1s; */
    animation-iteration-count: 1;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}

@keyframes moveDown { 100% { transform:translateY(-400px); }}
@keyframes moveDown1 { 100% { transform:translateY(-400px); }}
@keyframes moveDown2 { 100% { transform:translateY(-800px); }}
@keyframes moveDown3 { 100% { transform:translateY(-1200px); }}
@keyframes moveDown4 { 100% { transform:translateY(-1600px); }}
@keyframes moveDown5 { 100% { transform:translateY(-2000px); }}
@keyframes moveDown6 { 100% { transform:translateY(-2400px); }}
@keyframes moveDown7 { 100% { transform:translateY(-2800px); }}
@keyframes moveUp { 100% { transform:translateY(400px); } }
@keyframes moveUp1 { 100% { transform:translateY(400px); } }
@keyframes moveUp2 { 100% { transform:translateY(800px); } }
@keyframes moveUp3 { 100% { transform:translateY(1200px); } }
@keyframes moveUp4 { 100% { transform:translateY(1600px); } }
@keyframes moveUp5 { 100% { transform:translateY(2000px); } }
@keyframes moveUp6 { 100% { transform:translateY(2400px); } }
@keyframes moveUp7 { 100% { transform:translateY(2800px); } }
    var x, y;   // box の座標

    // 移動   1=上, 2=下
    function move(direct) {

        const objBox = document.getElementById("box");
        const cssStyle = window.getComputedStyle(objBox);
        y = parseInt(cssStyle.top.match(/(.*)px/)[1]);

        let anim = '';
        let divno = 0;     // 変更後の表示位置
        switch (direct) {
            case 1: 
                if (y >= -2400) {
                    anim = 'moveDown'; 
                    divno = ((y / -400) + 1);     // 変更後の表示位置
                }
                break;
            case 2: 
                if (y <= -400) {
                    anim = 'moveUp';
                    divno = ((y / -400) - 1);     // 変更後の表示位置
                }
                break;
        }

        if (anim !== '') {
            document.getElementById('divno').selectedIndex = divno;    // コンボボックスの値変更
            objBox.style.animationDuration = '1s';        // アニメの実行速度設定
            objBox.style.animationName = anim;  // アニメ開始
            btnsDisabled(true); // ボタン無効化
        }
    }

    // コンボボックス変更時
    function selected() {
        const objBox = document.getElementById("box");
        const cssStyle = window.getComputedStyle(objBox);
        y = parseInt(cssStyle.top.match(/(.*)px/)[1]);

        let anim = '';
        let divnofrom = (y / -400); // 現在の表示位置
        let divnoto = document.getElementById('divno').selectedIndex; // 移動先の表示位置
        let move = 0;    // 移動距離
        if (divnofrom < divnoto){
            move = (divnoto - divnofrom);
            anim = 'moveDown' + move;
        }else if (divnofrom > divnoto){
            move = (divnofrom - divnoto);
            anim = 'moveUp' + move;
        }

        if (anim !== '') {
            objBox.style.animationDuration = move + 's';    // アニメの実行速度設定
            objBox.style.animationName = anim;  // アニメ開始
            btnsDisabled(true); // ボタン無効化
        }
    }

    // animation 終了時の処理
    document.addEventListener('animationend', () => {
        const objBox = document.getElementById("box");
        const cssStyle = window.getComputedStyle(objBox);
        const arr = cssStyle.transform.match(/\((.*)\)/)[1].split(",");     // 文字列 matrix(a, b, c, d, cx, cy) を分解
        y += parseInt(arr[5]);  // transform.y の値を加える

        objBox.style.transform = '';        // アニメした transform を消す
        objBox.style.top = y + 'px';
        objBox.style.animationName = '';    // animationName を消す。こうしないと、次回に同じ方向のアニメが効かない。

        btnsDisabled(false);    // ボタン有効化
    });

    // 矢印ボタンの有効化/無効化
    function btnsDisabled(arg) {
        let btns = document.getElementsByTagName("input");
        for (let i = 0; i < btns.length; i++) {
            btns[i].disabled = arg;
        }
        document.getElementById('divno').disabled = arg;    // コンボボックス
    }

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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