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

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

ただいまの
回答率

90.76%

  • JavaScript

    15307questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    6324questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • HTML5

    3728questions

    HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

  • CSS3

    1917questions

    CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

javascriptのみでイージングの効いたアニメーションを実装したい

解決済

回答 5

投稿

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

owl

score 33

前提・実現したいこと

jQueryなどのプラグインを使わずにJavaScriptのみでイージングの効いたアニメーションを実現させたいです。

現状としましてはsetIntervalを使い、0.01秒間隔でidがboxの要素のcssにプラス一づつ増やしていき、横に動かしています。
値が200以上になるとclearIntervalを使ってストップさせています。
ここまでは実装できたのですが、200に近づくにつれて移動速度を遅くしたい(イージングさせたい)と思っています。

試したこと

プラス2づつ増やしていき、例えば150以上になったらプラス1づつに変更させてみたのですが、当たり前ですが、急にがくんと変化し、この考え方だと160以上ならプラス0.5づつ、170以上なら0.25ずつ増やすといったやり方になってしまうため、汎用性がないと思います。

該当のソースコードをjsfiddleにアップしていますので、
ご活用ください。
https://jsfiddle.net/ululami/54faxmgm/

ご回答、アドバイスよろしくお願いいたします。

該当のソースコード

var timer;
var xPosition = 0;

timer = setInterval('moveBox();', 10);

function moveBox(){
  xPosition ++;
    document.getElementById('box').style.left = xPosition + 'px';

    if(xPosition >= 200){
      clearInterval(timer);
    }
}
<div id="box"></div>
#box{
  width: 100px;
  height: 100px;
  background: tomato;
  position: relative;;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • SurferOnWww

    2017/10/02 09:46

    CSS3 の animation (例: https://www.w3schools.com/css/css3_animations.asp ) は質問者さんの目的に使えないでしょうか? (検討したが使えないという結論になったとか、勉強のため JavaScript でやりたいということでしたら失礼しました。でも、その場合はそのことも質問に書いておいていただけると助かります)

    キャンセル

  • owl

    2017/10/02 09:52

    ご返答ありがとうございます。SurferOnWwwさんの推察通り勉強のためにjsのみを使う感じです。記入不足で申し訳ないです。

    キャンセル

回答 5

checkベストアンサー

+7

このようなアニメーションを実現する場合, アニメーション開始後の「位置を加算していく」のではなく「ある時刻の位置を計算する」(タイムラインアニメーション)ようにします.

こうするとアニメーションの進み具合(進捗度)を考えることが出来て, この値から実際のアニメーション位置を決定するイージング関数を挟むことが可能となります

これはCSSやjQuery等に共通するWEBにおけるアニメーションの標準的な考え方です.

https://jsfiddle.net/defghi1977/54faxmgm/5/

document.addEventListener("DOMContentLoaded", function(){
  "use strict";
  //タイマー識別子
  var timer;
  //アニメーション開始時刻
  var begin;
  //アニメーション持続ミリ秒
  var dur = 2000;
  //アニメーション開始値
  var from = 0;
  //アニメーション終了値
  var to = 200;
  //アニメーション対象
  var style = document.getElementById("box").style;
  //イージング関数
  function easing(progress){
    return Math.pow(progress, 0.5);
  }
  //アニメーションを行う関数
  function moveBox(){
    //アニメーションの進捗(0〜1)
    var progress = (Date.now() - begin) / dur;
    if(progress > 1){
        progress = 1;
    }
    style.left = (from + (to - from) * easing(progress)) + 'px';
    //進捗が1になったら処理を停止
    if(progress == 1){
      clearInterval(timer);
    }
  }
  //アニメーションの実行
  begin = Date.now();
  timer = setInterval(moveBox, 10);
});

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/02 11:32 編集

    お節介かもしれませんがjsfiddleのほうでアニメーションがうまくいってないみたいです。
    javascriptのLOAD TYPEを変更したらうまくいったので、もし暇がありましたら直してみてはいかがでしょうか?

    キャンセル

  • 2017/10/02 11:58

    直してみました

    キャンセル

  • 2017/10/04 22:16

    ご回答ありがとうございます。
    時刻の位置を計算する方法だととてもスムーズなアニメーションで感動しました。またこの考え方はWEBにおける標準的な考え方のようですので、しっかりと勉強します。
    本当にありがとうございました。

    キャンセル

+5

jsFiddleを更新してみました。
様々な種類のイージングを見れます。

https://jsfiddle.net/54faxmgm/3/

イージングとは、時間経過に対して特定の計算をすることで、グラフの曲線を得るものになっていますので、「スタート」「ゴール」「現在時刻」から割合を求めて特定の計算式に投げ込むことで結果を得られます。このグラフが参考になるでしょう。
http://easings.net/ja

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/04 22:21

    ご回答ありがとうございます。
    たくさんのサンプルをありがとうございます。
    とてもわかりやすく、スムーズに動かすにはちゃんとした計算が必要だと理解できました。
    本当にありがとうございます。

    キャンセル

+3

調べてみたところ2次関数を使ったりするのが一般的みたいですね。

フォークして試しに2次関数を組み込んでみました。

ちょっと変数がごちゃついてしまいましたが。。(^ ^;
新たに定義したquad()がミソです。

var timer;
var intrvl = 10;
var t = 0;
var xPosition = 0;
var end = 200;
var endSec = end*intrvl;

timer = setInterval('moveBox();', intrvl);

function moveBox(){
    t += intrvl;
  xPosition = quad(t);
    document.getElementById('box').style.left = xPosition + 'px';

    if(xPosition >= end){
      clearInterval(timer);
    }
}

function quad(time){
    return -(Math.pow((time-endSec),2))/(endSec*intrvl)+end;
}

jsfiddle

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/04 22:23

    ご回答ありがとうございます。
    実際のサンプルはとても参考になりました。
    2次関数が鍵みたいですので、これから勉強してみます。
    本当にありがとうございます。

    キャンセル

+3

transform は使わないですか?

element.style.transition = 'transform 1s ease';
element.style.transform = 'translateX(200px)';


もしくはleft

element.style.transition = 'left 1s ease';
element.style.left = '200px';


ease -> ease-out, ease-in に変更など

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/04 23:23

    ご回答ありがとうございます。
    できるだけjavascriptで計算をしてやりたかったのですが、
    この方法もあると勉強になりました。
    本当にありがとうございます。

    キャンセル

+3

この手の処理を自前で用意したいなら、0から1までの範囲を動くグラフを書いてみることです。
加速度的に処理を早めるならy=x^n、遅くするならy=x^(1/n)するといいでしょう

<script>
window.onload=function(){
  var hoge1=document.querySelector("#hoge1");
  var hoge2=document.querySelector("#hoge2");
  var hoge3=document.querySelector("#hoge3");
  var hoge4=document.querySelector("#hoge4");
  var hoge5=document.querySelector("#hoge5");
  var i=1;
  var ms=1000;//ミリ秒
  var stp=100;//刻み
  var dst=300;//距離
  var timerId=setInterval(function(){
    hoge1.style.marginLeft=(Math.pow(i/stp,1/3)*dst)+"px";
    hoge2.style.marginLeft=(Math.pow(i/stp,1  )*dst)+"px";
    hoge3.style.marginLeft=(Math.pow(i/stp,2  )*dst)+"px";
    hoge4.style.marginLeft=(Math.pow(i/stp,3  )*dst)+"px";
    hoge5.style.marginLeft=(Math.pow(i/stp,10 )*dst)+"px";
    i++;
    if(i>stp){
      clearInterval(timerId);
    }
  },ms/stp);
}
</script>
<div id="hoge1" style="position:relative;background-Color:blue;width:100px;height:100px"></div>
<div id="hoge2" style="position:relative;background-Color:aqua;width:100px;height:100px"></div>
<div id="hoge3" style="position:relative;background-Color:lime;width:100px;height:100px"></div>
<div id="hoge4" style="position:relative;background-Color:yellow;width:100px;height:100px"></div>
<div id="hoge5" style="position:relative;background-Color:gray;width:100px;height:100px"></div>

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/04 22:18

    ご回答ありがとうございます。
    まずはグラフから考える必要があると改めて奥の深さに感動しました
    またサンプルもあり非常にわかりやすかったです。
    本当にありがとうございます。

    キャンセル

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

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

関連した質問

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

  • JavaScript

    15307questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    6324questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • HTML5

    3728questions

    HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

  • CSS3

    1917questions

    CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。