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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

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

Q&A

解決済

2回答

1392閲覧

js requestAnimationFrameのイージング

cheche0830

総合スコア187

JavaScript

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

0グッド

0クリップ

投稿2018/09/13 03:20

animate(); function animate() { requestAnimationFrame( animate ); render(); } var count = 0; function render() { var element = document.getElementById("test"); count += 1; element.style.width = count+"px"; }

要素の横幅を1pxずつひろげているのですが、
こちらを最初早く移動して最後は収束して一定の幅でとまるようにしたいのですが、
(いわゆるイージングです)可能でしょうか?

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

当然可能です。

requestAnimationFrame() 関数のコールバックは引数にタイムスタンプを受け取るので、
タイムスタンプから、前回の呼び出しから経過した時間を計算します。

経過時間が得られたら、経過時間を処理にかける予定の時間で割って進捗率とし、
進捗率に従って横幅を計算します。

横幅は

math

1横幅 = 開始時の横幅 + 変化率 * (最終的な横幅 - 開始時の横幅)

で計算できます。

この変化率は、進捗率そのものを利用すれば一定ペースでの変化に、
進捗率に対し原点を通り(1,1) を通る単調増加関数をかければ、関数に従って緩急の付いた変化になります。

質問者様の要望は終点付近で緩やかな変化になるものなので、(1,1) 付近で傾きが小さくなる関数が望ましいです。

該当する関数としては、平方根や n乗根、 sin 関数などでしょうか。
(n乗根の計算は難しいですし、sin 関数は (1, 1) を通るように係数を工夫する必要がありますが)

以下にサンプルコードを用意しましたので、参考にしてください。

html

1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="UTF-8"> 5 <style> 6 span{ background-color: red; height: 10px; width: 0px; display: inline-block; } 7 </style> 8 <script> 9 var TIME_LENGTH = 1000; // 処理に要する時間 (ミリ秒) 10 var WIDTH = [0, 500]; // 要素幅の [初期値, 終端値] 11 var start = null; // 処理開始時のタイムスタンプ 12 13 /** 14 * requestAnimationFrame のコールバックに指定する関数 15 * @param {number} timestamp タイムスタンプ 16 */ 17 function animate(timestamp) { 18 if(!start) start = timestamp; // 初回のみ、start 値を初期化 19 var progress = (timestamp - start) / TIME_LENGTH; // 経過した時間率 20 if(progress>1) progress = 1; 21 render(progress); 22 if(progress<1) requestAnimationFrame( animate ); 23 // 目的の幅に到達していない場合は、次の呼び出しを予約する 24 } 25 26 /** 27 * 要素の幅を更新する関数。 28 * @param {number} progress 時間の経過した割合 [0-1] 29 */ 30 function render(progress) { 31 var widthSpan = WIDTH[1] - WIDTH[0]; // 変化幅 32 document.getElementById("linear").style.width 33 = (WIDTH[0] + widthSpan * (progress*1)) + 'px'; // 一定ペース 34 document.getElementById("sqrt").style.width 35 = (WIDTH[0] + widthSpan * Math.sqrt(progress)) + 'px'; // 平方根 36 document.getElementById("sin").style.width 37 = (WIDTH[0] + widthSpan * Math.sin(progress*Math.PI/2)) + 'px'; // 円弧 38 } 39 /** 40 * アニメーションを開始する。 41 */ 42 function startAnimation(){ 43 start = null; 44 requestAnimationFrame(animate); 45 } 46 </script> 47 48</head> 49<body> 50 <button onclick="startAnimation()">アニメ開始</button> 51 52 <div>一定ペース:<span id="linear" style="background-color: red; height: 10px;" /></div> 53 <div>平方根  :<span id="sqrt" style="background-color: red; height: 10px;" /></div> 54 <div>円弧   :<span id="sin" style="background-color: red; height: 10px;" /></div> 55 56</body> 57</html> 58

投稿2018/09/13 05:43

R.Mizukami

総合スコア1086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cheche0830

2018/09/13 05:57

ありがとうございます!sinがきれいですね。試してみます!
guest

0

もちろん可能ですが、CSSのほうが簡単では?
https://teratail.com/questions/94669

投稿2018/09/13 04:23

x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cheche0830

2018/09/13 05:57

ありがとうございます!実際動かす内容がwebGLでして・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問