let n = 0; let flag = 1; function updown() { n += flag; if(count === 5) {flag = -1;} if(count === 0) {flag = 1;} } setInterval(updown,1000);
こんにちは、「ふ」です。
JavaScriptでカウンターを作り、「0, 1, 2..」と増やしていくのはすぐにできます。
では。これ⬇︎はどうでしょうか。
0, 1, 2, 3, 2, 1, 0, 1, 2 ..
指定した範囲で、加算と減算をくりかえす「往復カウンター」。
「これどーやるんだ?」と結構悩んだので、記事にしました。
〜というわけで今回紹介するのは「往復カウンター」の作り方。
単なるカウンターとしてに留まらず、setIntervalなどの段階的処理を往復させたいときにも使えます。またこの仕組みはJavaScriptに限らず、他のプログラム言語でも使うことができます。
〜押さえておきましょう。
それでは仕組みを解説していきます。
ただ加算していくだけのカウンターであれば、↓のようなコードが考えられます。
let n = 0; function a() { n += 1; } setInterval(a,1000);
変数nを用意しておき、nに1を加算する関数aを定義。setInternalで一定時間毎にaを実行していく、というものです。
当然ですがこれを繰り返すと、nは上限なく増えていってしまいます。
どこかで減算に切り替えたい。
if(n === 5) { n -= 1; }
⬆︎のように、nがある条件に達したら減算させる、という処理を思いつくかもしれません。しかしこれでは次回関数が実行されたときには減算条件に当てはまらなくなるので、またそこで加算が始まってしまいます。
ここは減算させるのではなく「マイナスの値を加算させる」という考え方でいきます。加算処理の内容が
n += 1;
となっていましたが、右辺の部分を具体的な数値ではなく変数にしておきます。
n += flag;
nには常にflagの値が加算されます。
if(条件) { flag = -1; }
そして、ある条件に達したときにflagの値を負の数にする。そうするとnは減算されるようになります。
次回関数実行時には条件には当てはまらないのですが、負の数になったflagは変更されることはありません。そのまま減算が繰り返されます。
カウンターの往復ということで、0になったらまたflagを正の数にして加算状態にするようにしましょう。
<p id = "number">0</p>
0
それでは往復カウンターを実際につくってみましょう。
テキスト要素⬆︎の表示を0〜5の間で往復変化させます。
「「3//要素を取得」」「「1 ..@1@」」 const number = document.getElementById("number"); 「「3//カウント変数」」「「1 ..@2@」」 let n = 0; 「「3//フラグ変数」」「「1 ..@3@」」 let flag = 1; function round_trip() { n+=flag; 「「3//始点と終点の条件分岐」」「「1 ..@4@」」 if(n === 5) { flag = -1; } else if(n === 0) { flag = 1; } 「「3//テキスト要素に反映」」「「1 ..@5@」」 number.textContent = String(n); } 「「3//0.5s毎に実行」」「「1 ..@6@」」 setInterval(round_trip,500);
@1@ テキスト要素を取得。
@2@@3@ 実際に表示されるカウント変数nと、フラグ変数flagを用意。
@4@ 関数round_trip内でnにflagを加算したあと、2つの条件分岐をしています。
・カウントが5になったらflagを-1とし、以降は減算開始。
・カウント0になったらflagを1に戻し、加算に切り替え。
初回関数実行時もnの値は0なので、問題なく加算状態からカウンターが始まります。
@5@ 取得した要素のテキストに反映させます。
@6@ setIntervalで、0.5s毎に関数〇〇を実行します。
0
往復カウンターができました。
往復カウンターを何らかのパラメータ値としてつかえば、様々な「処理の往復」に活用できます。
⬆︎は、幅400pxの<div>領域に合計幅800pxの小要素を詰め込んだもの。水平にスクロールさせることができます。
この水平スクロールを、自動で往復させてみましょう。往復カウンターを「スクロール量のパラメータ」に利用します。
「「3//親要素を取得・カウントとフラグを用意」」「「1 ..@1@」」 const box = document.getElementById("box"); let sn = 0; let sflag = 5; 「「3//手動によるスクロールを無効化」」「「1 ..@2@」」 box.addEventListener("touchmove",(event)=>event.preventDefault,{passive:false}); box.addEventListener("mousewheel",(event)=>event.preventDefault,{passive:false}); function scroll_reverse() { sn += sflag; 「「3//始点と終点に余裕を持たせる」」「「1 ..@3@」」 if(sn === 450) { sflag = -5; } else if (sn === -50) { sflag = 5; } 「「3//スクロール量に反映」」「「1 ..@4@」」 box.scrollTo(sn,0); } 「「3//1/50秒毎に実行」」「「1 ..@5@」」 setInterval(scroll_reverse,20);
@1@ 親要素のidは「box」ということにします。
要素を取得し、カウント変数snとフラグ変数sflagを定義。snはのちに1回あたりのスクロール量として使うのですが、1pxずつスクロールさせるのは気が遠くなるので、初期値を「5」としました。
@2@ 自動でスクロールを往復させるため、手動によるスクロール操作を無効にしておきます。
@3@ 定義した関数scroll_reverseにて。
snにsflagを加算したあと、スクロールの始点と終点でsflagが切り替わるようにします。
小要素の合計幅は800pxなので、400pxの親要素に対して本来のスクロール範囲は0px〜400pxです。が、そのまんまで指定するとスクロール両端にに到達した瞬間、逆スクロールが始まってしまうのでちょっと、忙しない。
なので、スクロール端部で少し停止するよう、終点を450px・始点を-50pxに設定しました。
「-50px」というのはちょっと邪道ですが。ふふふ。
@4@ 加工したカウント変数snの値を、親要素のスクロール量に反映させます。
@5@ 定義した関数を0.02秒毎に実行。
できました。
往復カウンター、他にもいろんな往復操作に使えそうです。試してみてくださいね。
最後までお読みくださり、ありがとうございました。
今回紹介した往復カウンター、アルゴリズムと呼ぶにはほど遠いのかもしれませんが、こうした「仕組みづくり」に挑戦するのは楽しいものです。プログラミングの醍醐味ですね。
みなさんも一緒に楽しんでいきましょう〜ではまた〜 🎶
ベクターグラフィック、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。