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

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

ただいまの
回答率

88.19%

複数のcanvasアニメーションを画面内に入ったタイミングでスタートさせたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,335

aKusano

score 3721

前提・実現したいこと

AnimateCCで作成したcanvasアニメーションを1枚のHTMLに複数配置しています。
これを対象のcanvasが画面内に入ったタイミングでそれぞれスタートさせたいです。
配置されるcanvasの数や位置はページによって異なりますが、
できれば配置されるcanvas数に関係なく一括でコントロールできるようにしたいです。

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

1枚のHTMLに複数のcanvasを配置することはできたのですが、
全てロードのタイミングで同時にスタートしてしまいます。

該当のソースコード

<html>
<head>
<meta charset="UTF-8">
<meta name="authoring-tool" content="Adobe_Animate_CC">
<title>sample</title>
<!-- write your code here -->
<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
<script src="assetsratio_pc.js"></script>
<script src="assetsratio_sp.js"></script>
<script src="measuresratio.js"></script>
<script src="top.js"></script>
<script src="common.js"></script>

</head>
<body>

        <div id="animation_container0">
            <canvas id="canvas0" width="260" height="260"></canvas>
            <div id="dom_overlay_container0"></div>
        </div>


        <div style="height: 1000px">他のコンテンツ</div>

        <div id="animation_container1">
            <canvas id="canvas1" width="844" height="460"></canvas>
            <div id="dom_overlay_container1"></div>
        </div>

        <div style="height: 1000px">他のコンテンツ</div>

        <div id="animation_container2">
            <canvas id="canvas2" width="345" height="397"></canvas>
            <div id="dom_overlay_container2"></div>
        </div>

</body>
</html>


▼top.js

var stage;
var canvas0, stage0, exportRoot0, anim_container0, dom_overlay_container0, fnStartAnimation0;
var canvas1, stage1, exportRoot1, anim_container1, dom_overlay_container1, fnStartAnimation1;
var canvas2, stage2, exportRoot2, anim_container2, dom_overlay_container2, fnStartAnimation2;

function init0() {
    canvas0 = document.getElementById("canvas0");
    anim_container0 = document.getElementById("animation_container0");
    dom_overlay_container0 = document.getElementById("dom_overlay_container0");
    var comp=AdobeAn.getComposition("F0BA06869C574E0F86857DBBA02CE764");
    var lib0=comp.getLibrary();
    handleComplete0({},comp);
}

function init1() {
    canvas1 = document.getElementById("canvas1");
    anim_container1 = document.getElementById("animation_container1");
    dom_overlay_container1 = document.getElementById("dom_overlay_container1");
    var comp1=AdobeAn.getComposition("3F7DA3D3BA86453D9104575D4B4ABC7E");
    var lib1=comp1.getLibrary();
    handleComplete1({},comp1);
}

function init2() {
    canvas2 = document.getElementById("canvas2");
    anim_container2 = document.getElementById("animation_container2");
    dom_overlay_container2 = document.getElementById("dom_overlay_container2");
    var comp2=AdobeAn.getComposition("32FC0171A22445EC84C8E9BEBB26ED91");
    var lib2=comp2.getLibrary();
    handleComplete2({},comp2);
}

function handleComplete0(evt,comp) {
    //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
    var lib0=comp.getLibrary();
    var ss0=comp.getSpriteSheet();
    exportRoot0 = new lib0.measuresratio();
    stage = new lib0.Stage(canvas0);    
    stage.addChild(exportRoot0);
    //Registers the "tick" event listener.
    fnStartAnimation0 = function() {
        createjs.Ticker.setFPS(lib0.properties.fps);
        createjs.Ticker.addEventListener("tick", stage);
    }        
    //Code to support hidpi screens and responsive scaling.
    //AdobeAn.makeResponsive(false,'both',false,1,[canvas0,anim_container0,dom_overlay_container0]);    
    AdobeAn.compositionLoaded(lib0.properties.id);
    fnStartAnimation0();
}

function handleComplete1(evt,comp) {
    //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
    var lib1=comp.getLibrary();
    var ss1=comp.getSpriteSheet();
    exportRoot1 = new lib1.assetsratio_pc();
    stage1 = new lib1.Stage(canvas1);    
    stage1.addChild(exportRoot1);
    //Registers the "tick" event listener.
    fnStartAnimation1 = function() {
        createjs.Ticker.setFPS(lib1.properties.fps);
        createjs.Ticker.addEventListener("tick", stage1);
    }        
    //Code to support hidpi screens anwd responsive scaling.
    //AdobeAn.makeResponsive(false,'both',false,1,[canvas1,anim_container1,dom_overlay_container1]);    
    AdobeAn.compositionLoaded(lib1.properties.id);
    fnStartAnimation1();
}

function handleComplete2(evt,comp) {
    //This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
    var lib2=comp.getLibrary();
    var ss2=comp.getSpriteSheet();
    exportRoot2 = new lib2.assetsratio_sp();
    stage2 = new lib2.Stage(canvas2);    
    stage2.addChild(exportRoot2);
    //Registers the "tick" event listener.
    fnStartAnimation2 = function() {
        createjs.Ticker.setFPS(lib2.properties.fps);
        createjs.Ticker.addEventListener("tick", stage2);
    }        
    //Code to support hidpi screens anwd responsive scaling.
    //AdobeAn.makeResponsive(false,'both',false,1,[canvas2,anim_container2,dom_overlay_container2]);    
    AdobeAn.compositionLoaded(lib2.properties.id);
    fnStartAnimation2();
} 


▼common.js

$(function(){
    scrollAnimation();
    var $win = $(window);
    $win.on("load", function() {
        init0();
        init1();
        init2();
    });
});

/* ==========================================================
!Scroll Animation
========================================================== */
function scrollAnimation(){
    var AnimTrigger = $('[data-timing="scroll"]'); //アニメーショントリガー
    var windowHeight = $(window).height(); //ウインドウの高さ

    // ロードした際に可視範囲に入っていたら実行される
    $(window).on('load',function(){
        AnimTrigger.each(function(){
            var imgPos = $(this).offset().top; //「AnimTrigger」の位置

            if (imgPos < windowHeight){
                $(this).addClass("aniOn");
            }
        });
    });

    // スクロールした際に「AnimTrigger」ごとに、以下に記述する内容が実行される
    $(window).scroll(function (){
        var scroll = $(window).scrollTop(); //スクロールした量

        AnimTrigger.each(function(){
            var imgPos = $(this).offset().top; //「AnimTrigger」の位置

            //アニメーションする条件=「画面の下から1/5まできた時点でアニメーション」
            //if (scroll > imgPos - windowHeight + windowHeight/5){
                if (scroll > imgPos - windowHeight/2){
                $(this).addClass("aniOn");
            }
        });
    });
}

試したこと

canvasの他にcss animationで特定要素が画面に入ったらアニメーション効果をつけて出現する
ギミックを実装しており、そのために特定要素が画面に入ったら特定のclassを付与する関数scrollAnimation()は用意してあります。
その関数の中でclass付与するところに単純に init0(); init1(); init2(); を入れてみたりもしましたが、
loadのタイミングの方では発火せず、scrollのところではスクロール中何度も呼び出されてしまって大変なことになってしまいました。。

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

<script src="assetsratio_pc.js"></script>
<script src="assetsratio_sp.js"></script>
<script src="measuresratio.js"></script>

こちらはAnimateCCが書き出したcanvasアニメーション本体のJSをそのまま読み込んでいるだけになります。

AnimateCC、CreateJS、Canvasともにこれまで全く経験ありません。今回始めて扱うものになりますので
初歩的なことが分かってないと思いますが、どなたかご教授いただけますと助かります。。。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

loadのタイミングの方では発火せず、

    $(window).scroll(function (){
        /* 略 */
    }).scroll(); // 1回実行しておく

scrollのところではスクロール中何度も呼び出されてしまって大変なことになってしまいました。。 

1回実行したら、どこかに実行したというフラグを各カンバスごとに作っておいて、2回目以降は実行しなければよいのでは。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/13 11:30

    ありがとうございます!
    アドバイスを元に無事loadまたはscrollのタイミングで
    各canvasを実行させることができるようになりました!
    ついでにページ内のcanvas数が違った場合でも使い回せるようにしてみましたが、
    もし何か気になる所がありましたらアドバイスいただけますと幸いです!

    <script>
    $(function(){
    var $trigger = $("canvas");
    var windowHeight = $(window).height();
    var num = $trigger.length;
    var initArray = [];
    var initFlag = [];

    for(var i = 0; i < num; i++){
    var str = 'init'+i+'()';
    initArray.push(str);
    initFlag.push('false');
    }


    $(window).on("load",function(){
    $trigger.each(function(i){
    var pos = $(this).offset().top;
    if (pos < windowHeight){
    if(initFlag[i] == 'false'){
    eval(initArray[i]);
    initFlag.splice(i,'true');
    }
    }
    });
    });

    $(window).on("scroll",function(){
    var scroll = $(window).scrollTop();

    $trigger.each(function(i){
    var pos = $(this).offset().top;
    if (scroll > pos - windowHeight/2){
    if(initFlag[i] == 'false'){
    eval(initArray[i]);
    initFlag.splice(i,1,'true');
    }else{
    return;
    }

    }
    });
    });
    });
    </script>

    キャンセル

  • 2019/09/13 11:39

    あ、loadの方で1箇所間違ってました。
    ✕ initFlag.splice(i,'true');
    ○ initFlag.splice(i,1,'true');

    キャンセル

  • 2019/09/13 12:00

    別質問にしてもらうほうがよいとは思いますが、
    1. eval は使わない
    2. top.js を整理したほうがよい。handleComplete は一つの関数を使いまわせるし init も Id末尾が違うだけ
    3. load を分けて処理する理由がわからない(回答の1個目参照)
    4. windowHeightは画面幅が変わる際に変わる可能性が高いのでscrollイベント内で採るほうがよい
    くらいです。

    キャンセル

  • 2019/09/13 12:27

    ありがとうございます〜。
    top.jsについては、私もできれば全ページで使いまわしできるようにしたいな、とは思ってるのですが、途中で各Canvas固有の情報が2箇所ほど出てくるのでどうやって使いまわし出来るようにしようかな?というのをまだ思案中でした。
    今回とりあえず動くようにするのが先決だったので、この後更にブラッシュアップしてみたいと思います!
    詰まったらまた新たに質問させていただきますので、その際はぜひとも
    よろしくお願い申し上げます。m(_ _)m

    キャンセル

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

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

関連した質問

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