物体の減速運動 ver.0.0.1

position:absolute とされた div の領域をマウスでドラッグしたときに,Drop 後に慣性の法則で移動させるための JavaScript. 一応,等速度運動では,止まらないので,摩擦による減速を想定する.

とりあえず,ソースはこんな感じ.


function moving() {
  vx *= 0.99; vx = intVal(vx);                        /* 減速処理 */
  vy *= 0.99; vy = intVal(vy); 
  var dx = parseInt(div.style.left) + intVal(vx/10);  /* 移動距離計算 */
  var dy = parseInt(div.style.top)  + intVal(vy/10);
  if(dx < 0) {
    vx = -vx; dx = 0;                                 /* 移動領域制御 */
  } else if (dx > 500) {
    vx = -vx; dx = 500;
  }
  if(dy < 0) {
    vy = -vy; dy = 0;
  } else if(dy > 500) {
    vy = -vy; dy = 500;
  }
  div.style.left =  dx + 'px';                        /* 表示位置指定 */
  div.style.top  =  dy + 'px';
  div.removeChild(div.lastChild);
  div.appendChild(document.createTextNode("x:"+vx+" y:"+vy));
  if(Math.abs(vx) > 10 || Math.abs(vy) > 10) {        /* 再帰モドキ */
    setTimeout("moving()", 10);
  }
}
	     

この moving() を Drag&Drop の javascript の mouseup の時の動作の最後に setTimeout("moving()",10); のような形で追加して動作をさせる.同じく初速の計算も, mouseup時に行なう.ここでは,mousedown 時点のマウスの座標から,mouseup での座標の差分を方向ベクトルとして,移動時間でベクトルの大きさを決定している.もしかするともう少し適切な方法があるかもしれない.

このとき,style の left, top には整数値しか利用できないので, 下記のような関数を作成して整数部のみを取り出した.


function intVal(n) {
  return (n > 0) ? Math.floor(n) : Math.ceil(n);
}
	     

floor のみだと,負の整数も正の整数として出力され, ceil だと繰り上げなため,最終的な速度が 0 に近い状態になれない場合があるので注意が必要.

ToDo
  • マウスの移動速度の取り方の工夫が必要
  • 速度が速すぎるときには描画タイミングで対応したほうがよい?