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

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

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

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

Q&A

解決済

2回答

3155閲覧

javascriptのスライドアニメーション 右斜め下への移動について

higulasi

総合スコア12

JavaScript

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

0グッド

0クリップ

投稿2023/10/05 06:25

実現したいこと

boxを右斜め下へ、(x、y)=(500px、300px)へ2秒かけて移動するスライドアニメーションを作成したい

前提

ここに質問の内容を詳しく書いてください。

画像にあるboxをクリックすると右斜め下へ移動し、リセットボタンを押すと戻るというのを記述したのですが、
現時点では右斜め下へ500px動いております。

これを右500px、下300pxという、バラバラの数値で実行したいのですが、うまく行きません。

このコードの流れとしては、
1、slideaAnimation()にて(element,direction,distance,duration)を記述。position変数を設定し0を格納
2、slide()にて、ボタンをクリック後にpositionに1ずつ加算していく
3、もしposition < distanceなら、directionに記述した内容が一致すればtranslate(${position}px,${position}pxまで動く
4、position > directionになったら、clearnIntervalでslide()を止める
5、slideAnimation()にそれぞれ記述し、動く。

ですが、どうやっても右と下で別々の距離が設定できません。

行った対処としては、distanceとpositionをそれぞれ2つに分け、それを置き換えて記述もしたのですが、斜めには動いても片方の数値でしか実行されませんでした。
これはどうしたら右斜め下、500px、300pxと動かすことができるのでしょうか?
お詳しい方がいましたら教えていただけないでしょうか?

よろしくお願いいたします

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

Javascript

1ソースコード
<body> <div class="place"> <button onclick="styleReset()">リセット</button> <div id="box" onclick="boxslideAimation()"> <p>box</p> </div> </div> <script> var sw = 0; console.log(sw)
const boxAnimation = document.getElementById("box"); function boxslideAimation(){ if(sw == 0) { const element = document.getElementById("box"); function slideAnimation(element, direction, distance, duration) { let position = 0; function slide() { position += 1; // if (position < distance) { if (direction === "rightdown") { element.style.transform = `translate(${position}px,${position}px)`; sw = 1; } }else { clearInterval(slide); } } setInterval(slide, duration); } slideAnimation(element, "rightdown", (500,300), 2); }else if(sw > 1) { } } function styleReset(){ const boxreset = document.getElementById("box") boxreset.style.transform = `translate(0px,0px)`; sw = 0; }
</script> </body> ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2023-10-05/d14bf2fd-5c8c-43aa-9040-ece32d81c132.png)

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

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

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

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

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

int32_t

2023/10/05 06:49 編集

何ミリ秒で移動を完了したいのでしょうか? 1000ms? 600ms?
higulasi

2023/10/05 06:50

2000ms(2秒)です!
int32_t

2023/10/05 07:13

おっとすみません、質問文に書いてありましたね。
higulasi

2023/10/05 07:14

いえ!回答していただけるだけでありがたく、嬉しいです!
guest

回答2

0

いまのコードだと「2ms 毎に 1px ずつ動かす」となってますが、それだと「2000ms で指定の量の移動がおわる」とはなりません。

いまのコードをベースにして考えると、slide()が1000回 (duration * 1000ms / 2ms) 呼ばれたときに目的の量になればいいので、translate() には ${Math.floor(distance * position / (duration * 1000 / 2))}px を指定しましょう。

  • 関数の引数の一つに (500,300) と書くと 300 だけが渡ります。一つの配列かオブジェクトに入れて渡すか2つの引数にしましょう。
  • 現在の一般的なシステムでは1秒間に500回も画面更新できません。秒間60回で充分です。setInterval() ではなく requestAnimationFrame() を使えばシステムの最適なタイミングで画面更新できます。

アニメーションAPIを使えばてっとり早いです。

js

1 element.animate( 2 [ 3 {transform:'translate(0px,0px)'}, 4 {transform:'translate(500px,300px)'} 5 ], {duration:2000}).onfinish = e => { 6 // アニメーションAPIでfillすると剥がすのが面倒なので手動fillする 7 element.style.transform = 'translate(500px, 300px)'; 8 };

投稿2023/10/05 07:28

編集2023/10/05 07:52
int32_t

総合スコア21929

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

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

higulasi

2023/10/05 08:43

回答ありがとうございます! 今、setInterval()をいただいた内容のrequestAnimationFrame()に置き換えたのですが、なんかよくわかんなくなっちゃいました。 ただ、アニメーション自体はいただいたコードで動いたので、もうちょっと勉強してみます!何度も助けていただき、ありがとうございます!
higulasi

2023/10/05 08:47

重ねて質問申し訳ないのですが、requestAnimationFrame()を使わないで記述することは不可能なのでしょうか? 私のもらった教材ですと、「setIntervalとclearIntervalでできるぜ」みたいに書かれているんですが、どうなんでしょうか?
int32_t

2023/10/05 09:04 編集

いまのままの setInterval() と clearInterval() でできますよ。requestAnimationFrame() を使うにはかなり書き換えが必要です。 学習中なら setInterval() と clearInterval() でアニメーションを組んでいいと思います。仕事でJavaScriptを組むようになると、setInterval() と clearInterval() は効率が悪いので怒られるかもしれません。
higulasi

2023/10/05 14:31

ありがとうございます!
guest

0

ベストアンサー

cssのkeyframeアニメーションがお手軽です

javascript

1<script> 2function boxslideAimation(){ 3 box.classList.add('slide'); 4} 5function styleReset(){ 6 box.classList.remove('slide'); 7} 8</script> 9<style> 10.place{ 11height:500px; 12background-Color:gray; 13} 14#box{ 15background-Color:yellow; 16width:100px; 17height:100px; 18} 19#box.slide{ 20animation:slide 2s; 21animation-fill-mode:forwards; 22} 23@keyframes slide{ 24 from{transform:translate(0px,0px)} 25 to{transform:translate(500px,300px)} 26} 27</style> 28<div class="place"> 29<button onclick="styleReset()">リセット</button> 30<div id="box" onclick="boxslideAimation()"> 31<p>box</p> 32</div> 33</div>

追記

jsバージョンです
CSS版とちょっと仕様がちがうので注意ください

javascript

1<script> 2function boxslideAimation(element,distances,duration){ 3 const myKeyframe= new KeyframeEffect( 4 element, 5 [ 6 {transform: `translate(0px,0px)`}, 7 {transform: `translate(${distances[0]}px,${distances[1]}px)`}, 8 ], 9 {duration,fill: "forwards" } 10 ); 11 const myAnime = new Animation(myKeyframe,document.timeline); 12 myAnime.play(); 13}; 14function styleReset(){ 15 boxslideAimation(box,[0,0],0); 16} 17</script> 18<style> 19.place{ 20height:500px; 21background-Color:gray; 22} 23#box{ 24background-Color:yellow; 25width:100px; 26height:100px; 27} 28</style> 29<div class="place"> 30<button onclick="styleReset()">リセット</button> 31<div id="box" onclick="boxslideAimation(this,[500,300],2000)"> 32<p>box</p> 33</div> 34</div>

調整版

移動中や移動後にboxをクリックしても反応しないようにする

javascript

1<script> 2function boxslideAimation(element,distances,duration){ 3 if(element.matches('[data-active]')) return false; 4 element.dataset.active=1 5 const myKeyframe= new KeyframeEffect( 6 element, 7 [ 8 {transform: `translate(0px,0px)`}, 9 {transform: `translate(${distances[0]}px,${distances[1]}px)`}, 10 ], 11 {duration,fill: "forwards" } 12 ); 13 const myAnime = new Animation(myKeyframe,document.timeline); 14 myAnime.play(); 15}; 16function styleReset(){ 17 delete(box.dataset.active); 18 boxslideAimation(box,[0,0],0); 19 delete(box.dataset.active); 20} 21</script> 22<style> 23.place{ 24height:500px; 25background-Color:gray; 26} 27#box{ 28background-Color:yellow; 29width:100px; 30height:100px; 31} 32</style> 33<div class="place"> 34<button onclick="styleReset()">リセット</button> 35<div id="box" onclick="boxslideAimation(this,[500,300],2000)"> 36<p>box</p> 37</div> 38</div>

投稿2023/10/05 07:24

編集2023/10/05 08:40
yambejp

総合スコア117691

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

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

higulasi

2023/10/05 07:38

回答ありがとうございます! 私もkeyflameでやりたいのですが、学校から「javascriptでやれや」と言われてしまってこうなりました... いただいたコードは今後の参考にさせていただきます!ありがとうございます!
yambejp

2023/10/05 07:48

クラスの付替えもjsでやっていることには変わらないんですけどね。 課題の指示がすべてjsでというのであれば追記したソースで行けると思います
higulasi

2023/10/05 08:19

今試してみたところ、無事に動きました!ありがとうございます! あとは移動中にクリックしても反応しないようにしていきます! ありがとうございました!
yambejp

2023/10/05 08:40

移動中や移動後にboxをクリックしても反応しない調整版を追記しておきました
higulasi

2023/10/05 08:50

ありがとうございます!めっちゃお仕事が早くてびっくりしてます...! ちなみに私もswって変数に数字を入れ替えする方法で無理やり押せないようにしたのですが、yamabe.jsさんのこの記述はどういった処理になるのでしょうか?
yambejp

2023/10/05 08:59

htmlにはカスタムデータという仕様があってdata-属性="xxx"で任意の属性が指定できます。 boxslideAimation()はdata-activeがついている間は反応しないようにし、 boxslideAimationが実行されたときにdata-activeを付加し、 styleReset()したときにdata-activeを外しています。 ただし、もとの位置に戻すためにリセットして移動してもう一度リセットする冗長な書き方になっています
higulasi

2023/10/05 14:30

ありがとうございます!勉強になります!
higulasi

2023/10/06 10:02 編集

すみません、いただいたコードでこんなことを言うのもアレなのですが、 1.boxをクリックする 2.動いている最中にリセットボタンを押す 3.アニメーションが終わったと同時に元の位置に戻る と言う現象が起きました そこで私は、sw = 0を作成して、 「もし0ならboxslideAnimationを実行する、実行の最後にsw=1にする。 0だったら何もしない。」 「もし1ならstyleResetを実行する、実行の最後にsw=0にする。 もし0なら何もしない。」 というつもりでコードを記述したのですが、その結果 1.boxをクリックしたらboxslideAnimationが実行、sw=1になる。 2.リセットを二回押すとsw=0になるが、boxが元の位置に戻らない 3.この状態で移動し切っているboxを押すと、開始地点の戻って動き始める という状態になってしまいました。 Q1.なぜ二回押さないとsw=0が代入されないのでしょうか? Q2.なぜsw == 1なのに、中身のboxが元の位置に戻る内容が実行されないのでしょうか? 重ねての質問で申し訳ないのですが、ぜひ教えていただきたいです 記述したコード var sw = 0; console.log(sw) function boxslideAimation(element,distances,duration){ if(sw == "0"){ if(element.matches('[data-active]')) return false; element.dataset.active=1 const myKeyframe= new KeyframeEffect( element,[ {transform: `translate(0px,0px)`}, {transform: `translate(${distances[0]}px,${distances[1]}px)`}, ], {duration,fill: "forwards" } ); const myAnime = new Animation(myKeyframe,document.timeline); myAnime.play(); sw = 1 console.log(sw) }else if(sw = "1"){ } } function styleReset(){ console.log(sw) if(sw == "1"){ delete(box.dataset.active); boxslideAimation(box,[0,0],0); delete(box.dataset.active); sw = 0 }else if(sw == "0"){ } }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問