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

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

ただいまの
回答率

89.99%

jQuery・要素がスクロールして画面内に入ったときのイベントが正しく再現されない

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 1,797

kyon

score 9

こんにちは。
下記のプラグインを使用して、要素が画面内に入ったときにフェードインさせるようと思っています。

http://creator.aainc.co.jp/archives/5357
引用テキスト要素がスクロールで画面内に入った時、内包要素を順番にフェードインするjQueryプラグインを作りました

書いてある通りに記述したのですが、要素を通り過ぎてからじゃないと表示されないのですが、一体なぜでしょう?

ちなみに、下記のプラグインも使用しています。

http://kyasper.com/jquery-tips/
jQuery とっても簡単、ページ内リンクでスムーズスクロール

<!doctype html>
<html lang="ja">
<head>
<meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1" /> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery-scrollInTurn.js"></script>

<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<script>
$(function(){
   $('a[href^=#]').click(function() {
      var speed = 400;
      var href= $(this).attr("href");
      var target = $(href == "#" || href == "" ? 'html' : href);
      var position = target.offset().top;
      $('body,html').animate({scrollTop:position}, speed, 'swing');
      return false;

      $()
   });

   $(document).ready(function() {
    $('.element').scrollInTurn();
  });

});
</script>

<meta charset="UTF-8">
<title> </title>
<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body><div class="element">
    <p><img src="images/.png" alt="画像" class="target" id="...image"/></p>
    <img src="images/.png" alt="画像" class="target" id="..image"/>
</div></body>
</html>
/*!
 * jQuery scrollInTurn plugin -version 1.0.1
 *
 *
 * Copyright 2014, Mayumi Tanji
 * Released under the MIT license
 * http://www.opensource.org/licenses/mit-license.php
 */

 (function( $ ){

  $.fn.scrollInTurn = function( options ) {

    var defaults = $.extend( {
      selector : '.target',
      delaySpeed : 300,
      fadeInSpeed : 300,
      fadeOutSpeed : 300,
      easing : 'swing',
      delayHeight : 500,
      fadeOutEvent : true
    }, options);

    return this.each(function() {

      var self = $(this);

      $(window).on('load',function(){
        self.find(defaults.selector).css({opacity: 0});
      });

      $(window).on('load scroll resize',function(){
        var target = self.find(defaults.selector);
        var elmTop = self.offset().top;
        var scrTop = $(window).scrollTop();
        var elmHeight = self.height();
        var windowHeight = $(window).height();
        if (scrTop > elmTop - defaults.delayHeight || scrTop + windowHeight > elmTop + elmHeight){
          if (!self.hasClass('on')) {
            target.each(function(i){
              $(this).delay(i*(defaults.delaySpeed)).animate({opacity:'1'}, defaults.fadeInSpeed, defaults.easing);
            });
            self.addClass('on');
          }
        }
        if (scrTop + windowHeight < elmTop){
          if (self.hasClass('on') && defaults.fadeOutEvent === true) {
            target.stop(true, true).animate({'opacity': 0}, defaults.fadeOutSpeed, defaults.easing);
            self.removeClass('on');
          }
        }
      });

    });

  };

})( jQuery );

初心者で至らない点もございますが、何卒よろしくお願いします!

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • yng13

    2016/01/08 14:47

    このコード、エラー発生せずに動きますか?

    キャンセル

回答 1

0

プラグインを使わなくてもできますよ。
jsFiddleのサンプル

jQueryオンリーではないですけど、多少のjavascriptは...(汗)

debounceというのでイベントを拾ってsetTimeoutする処理を別で書いてあります。jQueryでそれも読み込んで、本来$(window).on("scroll",function(...))とする部分を代用しています。

どこから説明するべきか迷いますが、まず通常こういうのは$.animateを使うと思います。
$.animateでdelayを入れて$.cssでプロパティをいじくるというのはできるんですが、例えば、

$(".test").animate ({
  marginTop: 10,
  opacity: 0
},{何かしらの処理})

こういうのを書くと、対象のマージンをいじくることになるので、それが入っている親要素の高さであったりが動いてしまいます(高さが変わるなど)。それでも問題ない場合はanimateを利用するのが良いですが、親要素の高さはなるべく変化せず、かつ中身の要素を動かしたい場合はtransform: translate(なにがし)を利用するのが良いです。

が、$.delayは$.animateなら普通に処理できるんですけれども$.animateが$.cssに変わると途端に効かなくなります。そこで、$.queue()を利用してやってます。

目的の要素が画面内に入ったかどうかは、その要素のオフセットを調べて、画面の表示領域と比較することで調べられます。また今回は、要素が一度画面から出た場合に再度入ってきたらまたアニメーションさせると言うことをしました。

transformを使っているために、回転や拡大縮小、移動や傾斜等複雑なアニメーションで表示することもできます。またこれらは、別途cssでクラス等を用意して、それらを付け替えるだけでもできるだろうと思います。

lazyloadなどでは、一度表示されたら表示されっぱなしなので(役目としてはそれで良いのですが)、そこはやはりまた動いて欲しい所。そのために、画面内に要素が入ってきて、アニメーションが終わったら.finishクラスをつけて、それがついてる間は表示しっぱなし、画面外に出たら.finishをとって画像を一旦非表示にし、また画面に入ったらアニメーションさせるということをしています。

スクリプトを見てもらうと結構行数があるように思いますが、コメントが入ってるから多く思うだけで、やってることは大したことをしているわけではありません。

注意点として、debounceでの処理は、いわゆるsetTimeoutなので、スクロールが完了した時に処理が開始されます。よってスクロール途中で画面外に出て更に画面内に入ったとしても入った時と変わらないので.finishクラスは外れません。

document.readyの段階で画像を非表示にするhideImage()で画像の最初の状態を作っています。opacityで非表示にして、translateYで位置をずらしているわけです。
画面内に入ったら、incrementFade()と言うのが動いてアニメーションしながら元の位置に戻ると言う事をしています。ここらがわかれば、好きなアニメーションで表示することはできるようになります。

またjQueryは3.0.0αバージョンでやっているので、今後も安泰です。
わかりませんけども(笑)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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