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

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

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

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

2回答

199閲覧

JavaScript flag関数 setInterval clearInterval 使い方

Shinnosuke0128

総合スコア3

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

1クリップ

投稿2024/04/15 12:38

実現したいこと

ボックスをクリックしたら2秒かけてボックスが右に500px、下に300pxの位置に動くようにしたい。
ボックスが動き終わったら、ボックスをクリックしても反応しずにリセットボタンをクリックすると、
リセットするようにした。
アニメーション中に二重処理が起きないように制御したい。
似たような質問がteratallにも掲載されているが、それを試してもやりたい動きにはならなかったので、質問します。

発生している問題・分からないこと

JavaScriptでsetInterval、clearInterval、flag関数を用いて、やると二重動作が起きなくなるのではないかと考えています。
そこで、下記のようなコードを入力したがボックスが動いた後にボックスをクリックしても、
また動き出してしまう。

該当のソースコード

JavaScript,html

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<title>lesson02 アニメーション1</title> 6<link rel="stylesheet" type="text/css" href="base.css"> 7</head> 8<body> 9<div id="wrapper"> 10<button id ="reset">リセット</button> 11<div id="box"> 12<p>box</p> 13</div><!-- box --> 14</div><!-- wrapper --> 15 16<script> 17function slideAnimation(target, moveX, moveY, duration) { // スライドアニメーションを申請する 18if(target.getAttribute("animating") !== null) return; // アニメーション中なら何もしない 19target.setAttribute("animating", ""); // 要素がアニメーション中であることを表す 20const startTime = performance.now(); // アニメーションを開始した時間を保存 21const intervalId = setInterval(slide, 1000 / 60); // 1秒/60フレーム=60fpsでslide関数を実行 22function slide() { // 経過時間に合わせて位置を変更する 23const nowTime = performance.now(); // 今の時間を保存 24const diffTime = nowTime - startTime; // 経過時間を保存 25if(diffTime >= duration) { // 経過時間がduration以上なら 26translate(target, moveX, moveY); // スライドの最後の状態にする(位置ズレ解消のため) 27target.removeAttribute("animating", ""); // 要素がアニメーション中でないことを表す 28clearInterval(intervalId); // インターバルを削除 29return; 30} 31const nowX = (moveX / duration) * diffTime, // 現在いるべきx座標を表す 32nowY = (moveY / duration) * diffTime; // 現在いるべきy座標を表す 33translate(target, nowX, nowY); // 現在いるべき座標の状態にする 34} 35} 36function translate(target, x, y) { // 位置をずらすための関数 37target.style.transform = `translate(${x}px, ${y}px)`; 38} 39 40document.querySelector("#box").addEventListener("click", e => { 41slideAnimation(e.currentTarget, 500, 300, 2000); // #boxを右に500px下に300pxを2000ミリ秒かけてスライドさせる 42}); 43document.querySelector("#reset").addEventListener("click", () => { 44translate(box, 0, 0); // #boxの位置をリセットする 45}); 46</script> 47</body> 48</html>

css

1@charset "UTF-8"; 2/* reset */ 3body, h1, h2, h3, h4, h5, h6, p, address, 4ul, ol, li, dl, dt, dd, img, form, table, tr, th, td { 5 margin: 0; 6 padding: 0; 7 border: none; 8 font-style: normal; 9 font-weight: normal; 10 font-size: 100%; 11 text-align: left; 12 list-style-type: none; 13 border-collapse: collapse; 14} 15 16textarea { font-size: 100%; vertical-align:middle;} 17img { border-style: none; display: block; } 18hr { display: none; } 19em{font-style: normal} 20input{line-height:auto;vertical-align:middle;} 21strong.more{color:#c30} 22a{text-decoration: none;} 23 24html { 25 26} 27 28body { 29 font-family:'ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ',Meiryo,'MS Pゴシック',sans-serif; 30} 31 32* { 33 -webkit-box-sizing: border-box; 34 -moz-box-sizing: border-box; 35 -o-box-sizing: border-box; 36 -ms-box-sizing: border-box; 37 box-sizing: border-box; 38} 39 40/* 上の部分は気にせずここから書く */ 41#box { 42 width: 320px; 43 height: 180px; 44 background-color: #fdd; 45 cursor: pointer; 46} 47 48#box p { 49 line-height: 180px; 50 font-size: 32px; 51 text-align: center; 52} 53

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

flag関数を用いて、やってみたり、clearIntervalの内容を変えてみたが、動作終了後でも、ボックスをクリックすると、また動き出してしまう。
また、打ったコードによっては、ボックスが動かなくなってしまったケースもあった。

補足

特になし

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

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

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

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

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

yambejp

2024/04/16 00:30

これと同じ質問はすでに数回回答済みだとは思いますが、setTimeout/setIntervalを利用するのは効率の悪い処理なのでおすすめしません。また二重処理はsetXXでなくてもフラグで管理すれば防げるでしょう
guest

回答2

0

target.removeAttribute("animating", "");slider() 中から #resetclick イベントリスナの中に移動するといいんじゃないでしょうか。


ところで、animating というHTML規格にない属性を勝手に使ってはいけません。こういう自分だけの属性を使いたいときは data- で始まる名前にする必要があります。

投稿2024/04/15 12:46

編集2024/04/15 22:16
int32_t

総合スコア20909

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

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

0

ベストアンサー

条件

  • ボックスをクリックしたら2秒かけてボックスが右に500px、下に300pxの位置に動く
  • ボックスの動作中・動き終わっても、ボックスをクリックしても反応しない
  • リセットボタンをクリックするとボックスを元の位置に戻す

考え方

  • カスタムデータでステータスを管理
  • ボックスやリセットのクリックでカスタムデータを付加

総じてこんな感じ

javascript

1<style> 2#box { 3 width: 320px; 4 height: 180px; 5 background-color: #fdd; 6 cursor: pointer; 7} 8#box p { 9 line-height: 180px; 10 font-size: 32px; 11 text-align: center; 12} 13</style> 14<div id="wrapper"> 15<button id ="reset">リセット</button> 16<div id="box"> 17<p>box</p> 18</div> 19</div> 20<script> 21function slideAnimation(target, moveX, moveY, duration) { 22 if(target.dataset.anime) return false; 23 target.dataset.anime=1; 24 const delay=10; 25 const start=new Date(); 26 const timerId=setInterval((function callback(){ 27 const passed=new Date()-start; 28 const rate=passed<duration?passed/duration:1; 29 target.style.transform=`translate(${moveX*rate}px,${moveY*rate}px)`; 30 if(ratio==1){ 31 clearInterval(timerId); 32 } 33 return callback; 34 })(),delay); 35} 36document.addEventListener('click',({target})=>{ 37 if(target.closest('#box')){ 38 const x=500; 39 const y=300; 40 const ms=2000; 41 slideAnimation(box,x,y,ms); 42 } 43 if(target.closest('#reset')){ 44 delete(box.dataset.anime); 45 box.style.transform=null; 46 } 47}); 48</script>

投稿2024/04/16 02:54

yambejp

総合スコア114876

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問