• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:JQueryのイーズインとイーズアウト)

JQueryのイーズインとイーズアウトの使い方とは?

このQ&Aのポイント
  • JQueryのscrollsmoothly.jsを使ってイーズインとイーズアウトのアニメーションを実装する方法について教えてください。
  • scrollsmoothly.jsでは、イーズアウトを使ってスタートはすっと動き、最後がゆっくり着地するアニメーションを作ることができます。しかし、イーズインとイーズアウトを組み合わせる方法がわかりません。
  • 製作者からは、イーズアウトしか考慮されていないため、イーズインとイーズアウトを組み合わせる場合は柔軟な対応が必要だとアドバイスを受けました。イージングについて調べて試してみましたが、上手く動作しません。具体的な方法を教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • yyr446
  • ベストアンサー率65% (870/1330)
回答No.3

【その後】 このロジックで、かなり強引に、「始めちょろちょろ中ぱっぱ終わりちょろちょろ」になるようなイージングが動作するようになったけど、この辺が限界か、大幅に書き換えた方がよいかも。 (変更した関数)    function setScroll(hash){     // ハッシュからターゲット要素の座標をゲットする     var targetEle = d.getElementById(hash.substr(1));     if(!targetEle)return;     //alert(scrollSize.height);     // スクロール先座標をセットする     var ele = targetEle;     var x = 0;     var y = 0;     while(ele){      x += ele.offsetLeft;      y += ele.offsetTop;      ele = ele.offsetParent;     }     var maxScroll = getScrollMaxXY();     targetX = Math.min(x, maxScroll.x);     targetY = Math.min(y, maxScroll.y);     targetHash = hash; //ここに挿入     x = d.documentElement.scrollLeft||d.body.scrollLeft;     y = d.documentElement.scrollTop||d.body.scrollTop;     if((targetX - x) >= 0)     centerX = Math.floor((targetX - x) / 2) + x;     else centerX = (Math.floor((targetX - x) / 2) + x) * -1;     if((targetY - y) >= 0)     centerY = Math.floor((targetY - y) / 2) + y;     else centerY = (Math.floor((targetY - y) / 2) + y) * -1; //ここまで     // スクロール停止中ならスクロール開始     if(!scrolling){      scrolling = true;      scroll();     }    }    function scroll(){     var currentX = d.documentElement.scrollLeft||d.body.scrollLeft;     var currentY = d.documentElement.scrollTop||d.body.scrollTop; //ここから書き換え     if(centerX >=0){     if(currentX >= centerX)       var vx = (targetX - currentX) * easing;      else var vx = currentX * easing + 1;     }else{     if(currentX < Math.abs(centerX))       var vx = (targetX - currentX) * easing;      else var vx = (2 * centerX + currentX) * easing - 1;     }     if(centerY >=0){     if(currentY >= centerY)      var vy = (targetY - currentY) * easing;      else var vy = currentY * easing + 1;     }else{     if(currentY < Math.abs(centerY))      var vy = (targetY - currentY) * easing;      else var vy = (2 * centerY + currentY) * easing - 1;     }     //console.log(targetY+":"+centerY+":"+currentY+":"+vy); //ここまで     var nextX = currentX + vx;     var nextY = currentY + vy;  ------- 以下変更なし。

ritzkun
質問者

お礼

回答No04の方の動きも試させていただきました。 狙っていた動きではありませんが、 逆にこっちの方が、かっこいいですね☆ うまく表現ができないのですが、 Section5からSection3に移動する際、 Section6に一度、移動しながらなめらかにSection3に上っていくような動きをします。 逆に、Section3からSection5に戻る際は Section1を通って動きます。 真横もしくは真下(Section3から1というように)に動くときは 狙った動きどうりに動きますし、ジャンプ移動中に別のリンクをクリックしても ちゃんと移動先がなめらかに切り替わります。 他の質問も含め、年末年始と、かなり助かりました!! 本当にありがとうございます☆ いろいろと試してみてまたわからないことがでてくるかと思いますので その際はご質問させていただきます☆ もし可能であれば回答No.04の方で補足させていただいている 質問も教えていただけると助かります☆

ritzkun
質問者

補足

本当にありがとうございます!! 見捨てられたかと思い、めちゃくちゃ困っていました・・・。 教えていただいた形でさせていただきますと、はじめゆっくり、中ぱっぱ おわりもゆっくりといった動きをするのですが、斜めに動くときにまっすぐに斜めに動かず、一度、横に動いてからあがる(下がる)といった動きになります・・・。 なぜでしょうか・・・? 回答No.04の方のものも一度試してみます☆

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.5

#4です。 >1)移動中はリンクをクリックできないようにする クリックしてもをキャンセルするという意味ですよね? そのあたりはオリジナルのままなのでキャンセルされるはず… と思って見直してみたら、クリックされたら以降の処理に関係なくtargetの座標を書換えちゃってくれるようになってますねぇ。 動作中だったら setScrollを実行する必要はないので、setScroll()の最初に  if (scrolling) return; を追加すればご質問のようになります。(そのほうが無駄な処理もなくなるし) >2)移動中にリンクをクリックした際は、そちらへ移動するようにかわる こちらの仕様のほうがリーズナブルかもしれませんね。 クリックされたら、スクロール中の処理を中断して新しいスクロールを始めるようにすれば良いのですが、オリジナルの骨格を利用しているので、修正箇所が分散します。 ついでに、移動速度が速いほうが良いらしいので(#3の補足を見て)、easingFuncも書換えてみました。(係数変えただけですけど) (早いブラウザだとあまり効果が感じられなくなってしまいましたが…) #4にも書いたように、この部分の関数を帰ることで動きの種類を変えることが可能になっています。⊿pを返す形式にしてしまったのでバウンスなどはできませんが、intervalや必要時間を変えられるようにして、タイマーと変化量の関係の関数にすれば、バウンドさせたりとかいろいろな移動形式を可能にできます。 (1)最初のほうの  var scrolling = false; → var scrolling = null; (2) setScrollの終わりのほうの4行  if(!scrolling){   scrolling = true;   scroll();  } の部分を   scroll(); の1行に置換え (3) 入替えたscroll()部分を以下に再度入替え function scroll(){  if (scrolling) clearInterval(scrolling); //追加  var startX = d.documentElement.scrollLeft||d.body.scrollLeft;  var startY = d.documentElement.scrollTop||d.body.scrollTop;  var deltaX = targetX - startX;  var deltaY = targetY - startY;  var progress = 0;  var limit = 0.9995;  scrolling = setInterval(function(){ //修正   progress += easingFunc(progress);   var x = startX + progress * deltaX;   var y = startY + progress * deltaY;   if(progress > limit) {    scrollTo(targetX, targetY); //終了処理部分を書換え    location.hash = targetHash;    clearInterval(scrolling);    scrolling = null;   }else{    scrollTo(parseInt(x), parseInt(y)); } }, interval); } function easingFunc(p) { // Sample4 var a = 1/3, r = p<0.5?p:(1-p); return Math.max(r * a, 0.008); } (1)~(3)の修正をすればご質問のようになりますが、速度を速くしたので移動中に正しくクリックするのが難しそう。 (動作確認は速度を遅くしてやりました)

すると、全ての回答が全文表示されます。
  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.4

No1様がすでにご指摘の部分を調整すれば良いみたいですが・・・ ちょっと効率は悪いですが、function scroll()部分の差替えの形にしてみました。 (あちこち変えると面倒なので、一箇所にまとめた…ので効率が悪い?) easingFunc()は進捗率p(=0~1)に対して、増加分⊿pを返す関数にしています。 この関数を書換える事で、動作を変えられるようになっています。 Sample1は等速運動、Sample2は三角関数で、Sample3はオリジナルに近い差分に対する比で増加分を決めています。 係数などを調整すれば、移動速度や変化の率などを変えられます。 (増加分を返す関数にしてしまったので、行きつ戻りつみたいなのはやりにくいですが…) * オリジナルサイトのサンプルで試す場合、HTMLのリンク先が絶対参照になっているため修正しないとオリジナルサイトへ遷移してしまい、スクリプトの変更がキャンセルされてしまいますのでご注意。(#2様が効果がわからないと書いておられるのはこのせいかも) //(全角空白は半角に) function scroll(){  var startX = d.documentElement.scrollLeft||d.body.scrollLeft;  var startY = d.documentElement.scrollTop||d.body.scrollTop;  var deltaX = targetX - startX;  var deltaY = targetY - startY;  var progress = 0;  var limit = 0.9995;  var timerId = setInterval(function() {   progress += easingFunc(progress);   var x = startX + progress * deltaX;   var y = startY + progress * deltaY;   if(progress > limit) {    // 目標座標付近に到達していたら終了    scrollTo(targetX, targetY);    scrolling = false;    location.hash = targetHash;    clearInterval(timerId);    timerId = null;   }else{    // 繰り返し    scrollTo(parseInt(x), parseInt(y));   }  }, interval); } function easingFunc(p) { // Sample1 easingなし(等速)  //return 0.05; // Sample2 sin曲線(増加率:a*cos)  //var a = 0.08, toRad = Math.PI * 0.999; //(p=0の時に0を回避のため)  //return Math.cos((p-0.5) * toRad) * a; // Sample3 漸近線(残差/a)  var a = 1/6, r = p<0.5?p:(1-p);  return Math.min(Math.max(r * a, 0.001), 0.1); }

ritzkun
質問者

補足

回答ありがとうございます!!大変助かりました。 イメージに近い動きになりました! 以前の質問(yyr446さんに回答いただいた別の質問)で ロード後、#section9から#section5まで移動するということを 教えていただき、そのように動かしているのですが そのままにしておくと、setcion1でロードし、section9まで飛んでいってしまいました。 // ドキュメント読み込み完了時の処理 function init(){ // ページ内リンクにイベントを設定する setOnClickHandler(); // 外部からページ内リンク付きで呼び出された場合 if(incomingHash){ if(window.attachEvent && !window.opera){ // IEの場合はちょっと待ってからスクロール setTimeout(function(){scrollTo(0,0);setScroll('#'+incomingHash);},200); }else{ // IE以外はそのままGO scrollTo(0, 0); setScroll('#'+incomingHash); } }   //ここから setScroll("#section5"); //←※01 setTimeout(function(){setScroll("#section5");},1000); //1秒後に移動   //ここまで } // イベントを追加する関数 ※01のsection名がもともとは9だったのですが5にかえると、キレイに動きましたので ここはクリアできました☆ ただ、ひとつ問題がございまして、 ジャンプ中(移動中)に別のリンクを押しても移動が途中で切り替わらず 最後に、パッとリンク先に切り替わってしまいます。 例えば、 1)移動中はリンクをクリックできないようにする 2)移動中にリンクをクリックした際は、そちらへ移動するようにかわる 方法にできますでしょうか? 質問に質問を繰り返し、申し訳ございませんが ご教授いただければ幸甚です。

すると、全ての回答が全文表示されます。
  • yyr446
  • ベストアンサー率65% (870/1330)
回答No.2

年末年始とほったらかしにしてすまんこってす。 変更箇所は、    function setScroll(hash){     // ハッシュからターゲット要素の座標をゲットする     var targetEle = d.getElementById(hash.substr(1));     if(!targetEle)return;     //alert(scrollSize.height);     // スクロール先座標をセットする     var ele = targetEle;     var x = 0;     var y = 0;     while(ele){      x += ele.offsetLeft;      y += ele.offsetTop;      ele = ele.offsetParent;     }     var maxScroll = getScrollMaxXY();     targetX = Math.min(x, maxScroll.x);     targetY = Math.min(y, maxScroll.y);     targetHash = hash; //ここに挿入     x = d.documentElement.scrollLeft||d.body.scrollLeft;     y = d.documentElement.scrollTop||d.body.scrollTop;     centerX = Math.floor((targetX - x) / 2);     centerY = Math.floor((targetY - y) / 2); //ここまで     // スクロール停止中ならスクロール開始     if(!scrolling){      scrolling = true;      scroll();     }    }    function scroll(){     var currentX = d.documentElement.scrollLeft||d.body.scrollLeft;     var currentY = d.documentElement.scrollTop||d.body.scrollTop; //ここから書き換え     //var vx = (targetX - currentX) * easing;     //var vy = (targetY - currentY) * easing;     if(currentX >= centerX) var vx = (targetX - currentX) * easing;     else var vx = (targetX - currentX) / easing;     if(currentY >= centerY) var vy = (targetY - currentY) * easing;     else var vy = (targetY - currentY) / easing; //ここまで     var nextX = currentX + vx;     var nextY = currentY + vy;     if((Math.abs(vx) < 1 && Math.abs(vy) < 1)      || (prevX === currentX && prevY === currentY)){      // 目標座標付近に到達していたら終了      scrollTo(targetX, targetY);      scrolling = false;      //location.hash = targetHash;      prevX = prevY = null;      return;     }else{      // 繰り返し      scrollTo(parseInt(nextX), parseInt(nextY));      prevX = currentX;      prevY = currentY;      setTimeout(function(){scroll()},interval);     }    } なんです。これで動作はするんですが、イーズインとイーズアウト が効いているのかどうか速すぎてよくわからんとゆうか、intervalミリ秒数増やしてみても、やっぱり効いて無いような気がします。しきりなおしですね。ぺこり

ritzkun
質問者

お礼

上記のお礼内を訂正します・・・。 -------------------------- 回答No04の方の動きも試させていただきました。 狙っていた動きではありませんが、 逆にこっちの方が、かっこいいですね☆ うまく表現ができないのですが、 -------------------------- ここの部分ですが、こっちの動きというのは yyr446さんの動きのことです。 すいません、読み直していて 誤解を与えそうなので注釈しておきます☆

すると、全ての回答が全文表示されます。
  • yyr446
  • ベストアンサー率65% (870/1330)
回答No.1

引き続き前の回答者です。 イーズインしてイーズアウトで終るようにしたいんですね、製作者様がヒントをくれてます。  先頭の方にある   var easing = 0.25;  これが、イージング率ですね。 改造するところは、function scroll(){}の中です。   var vx = (targetX - currentX) * easing;   var vy = (targetY - currentY) * easing;   var nextX = currentX + vx;   var nextY = currentY + vy; で、終わりに近づくにつれ、移動量 vx,vy が 小さくなっていってますね。 これを前半は真ん中に近づくまでは移動量 vx,vy が大きくなるようにし、 後半は小さくなるようにすればよいかと。 ※最初に真ん中の位置centerX,centerYを先頭で定義します。 そして、function setScroll(){}で計算してセットします。 targetHash = hash;の下あたりで、   x = d.documentElement.scrollLeft||d.body.scrollLeft;   y = d.documentElement.scrollTop||d.body.scrollTop;   centerX = Math.floor((targetX - x) / 2);   centerY = Math.floor((targety - y) / 2); としてから、   if(!scrolling){   scrolling = true;   scroll();   } そして、function scroll(){}の中で  if(currentX >= centerX) var vx = (targetX - currentX) * easing;   else var vx = (targetX - currentX) / easing;  if(currentY >= centerY) var vy = (targetY - currentY) * easing;   else var vy = (targetY - currentY) / easing; とする。 うーん、安直すぎてだめかも... いろいろお試しあれ!

ritzkun
質問者

お礼

なんども申し訳ございません・・・。 あれから色々と見直してみますと、せっかく教えていただいている部分を読み間違えている箇所がございました・・・。 教えていただいた「function setScroll」の「targetHash = hash;」の下あたりに挿入するあたりを上で勘違いしておりました。 しかし、やはり動きません・・・。 教えていただいた部分で2箇所わからないことがございます。 ■1) まず、centerX,Yをどこで定義すればよいのでしょうか? ------------------------------------ (function(){ var easing = 0.20; var interval = 100; //スピード ここに、   var centerX= 0; var centerY = 0; ------------------------------------ を追記すればよいのでしょうか? 初歩的な質問で申し訳ございません・・・。 ■2) 次に、「function scroll(){}の中に挿入する ------------------------------------  if(currentX >= centerX) var vx = (targetX - currentX) * easing;   else var vx = (targetX - currentX) / easing;  if(currentY >= centerY) var vy = (targetY - currentY) * easing;   else var vy = (targetY - currentY) / easing; ------------------------------------ これは、function scroll(){のどこに挿入すればよいのでしょうか? 現在、 function scroll(){ var currentX = d.documentElement.scrollLeft||d.body.scrollLeft; var currentY = d.documentElement.scrollTop||d.body.scrollTop; var vx = (targetX - currentX) * easing; var vy = (targetY - currentY) * easing; var nextX = currentX + vx; var nextY = currentY + vy; if((Math.abs(vx) < 1 && Math.abs(vy) < 1) || (prevX === currentX && prevY === currentY)){ // 目標座標付近に到達していたら終了 scrollTo(targetX, targetY); scrolling = false; //location.hash = targetHash; //コメントアウトをはずすとアンカーがでる。 prevX = prevY = null; return; }else{ // 繰り返し scrollTo(parseInt(nextX), parseInt(nextY)); prevX = currentX; prevY = currentY; setTimeout(function(){scroll()},interval); } となっており、 var currentX = d.documentElement.scrollLeft||d.body.scrollLeft; var currentY = d.documentElement.scrollTop||d.body.scrollTop; var vx = (targetX - currentX) * easing; var vy = (targetY - currentY) * easing; ここを削除して、差し替える方がよいのでしょうか? 色々試してみてはいるのですが、基礎的な部分がないため、わからないところがわからないような状態です・・・。 どうかご教授いただければ幸甚です。

ritzkun
質問者

補足

なんどもご回答ありがとうございます☆ ご教授いただいたのですが、動きませんでした・・・。 なにがわるかったのでしょうか? -------------------------- function scroll(){ var currentX = d.documentElement.scrollLeft||d.body.scrollLeft; var currentY = d.documentElement.scrollTop||d.body.scrollTop; var vx = (targetX - currentX) * easing; var vy = (targetY - currentY) * easing; var nextX = currentX + vx; var nextY = currentY + vy; if((Math.abs(vx) < 1 && Math.abs(vy) < 1) || (prevX === currentX && prevY === currentY)){ // 目標座標付近に到達していたら終了 scrollTo(targetX, targetY); scrolling = false; //location.hash = targetHash; ← ここは、コメントアウトしたままです。    //ここから    x = d.documentElement.scrollLeft||d.body.scrollLeft;    y = d.documentElement.scrollTop||d.body.scrollTop;   centerX = Math.floor((targetX - x) / 2);   centerY = Math.floor((targety - y) / 2); if(!scrolling){   scrolling = true;   scroll();   }         if(currentX >= centerX) var vx = (targetX - currentX) * easing;    else var vx = (targetX - currentX) / easing;    if(currentY >= centerY) var vy = (targetY - currentY) * easing;     else var vy = (targetY - currentY) / easing;     //ここまで挿入しました。 prevX = prevY = null; return; }else{ // 繰り返し scrollTo(parseInt(nextX), parseInt(nextY)); prevX = currentX; prevY = currentY; setTimeout(function(){scroll()},interval); } } -------------------------- 単純に、コピペしただけなのですが、最後のif(currentX >= centerX) var vx = (targetX - currentX) * easing;~あたりを どこにいれればいいかがよくわかりません・・・。 ここをいれなければ、動いているのですが(目的の動きではないです。)if(currentX >= centerX) var vx = (targetX - currentX) * easing;~を いれると、まったく動かなくなってしまいます。 function scroll(){のあとの、var vx あたりを消して、差換えてみたのですが やはり動きませんでした・・・。 年末のお忙しいときに申し訳ございませんが何卒ご教授くださいませ・・・。

すると、全ての回答が全文表示されます。

関連するQ&A