日々是好日~every day is a good day~

日常の中の非日常の備忘録

【JavaScript】ジョイスティックボールと自転・公転

以前アップした「WebARラジコンヘリコプター」のジョイスティックボールに関するスクリプト部分にバグが見つかったので
「WebVRプラネット」ではその部分を修正しています
なのでジョイスティックボールのスクリプトとあと自転・公転のスクリプトを残しておきます

ジョイスティックボール

      var ballCenterX; //ballの中心座標X
      var ballCenterY; //ballの中心座標Y
      var ballRad; //ballの中央からの角度
      var shiftX; //ballが移動した時の中心の補正X
      var shiftY; //ballが移動した時の中心の補正Y
      var moveSpeed = 0; //カメラのスピード
      var movex = 0; //ballのX->カメラ移動X方向
      var movey = 0; //ballのY->カメラ移動Z方向
      var moving; //ID
      var cnt = 0; //移動回数
      var direction; //進行方向
      var camPos; //カメラの位置
      var camRot; //カメラの回転

      const ball = document.querySelector("#joystick-ball");
      const ballRadius = ball.clientWidth / 2;
      const frame = document.querySelector("#joystick-frame");
      const frameCenterX =
        frame.getBoundingClientRect().left + frame.clientWidth / 2;
      const frameCenterY =
        frame.getBoundingClientRect().top + frame.clientHeight / 2;
      const frameRadius = frame.clientWidth / 2;
      const camera = document.querySelector("#camera");

      ball.addEventListener("touchstart", touchStart);

      function touchStart(e) {
        e.preventDefault();
        shiftX = e.touches[0].clientX - frame.clientWidth / 2;
        shiftY = e.touches[0].clientY - frame.clientHeight / 2;
        ball.style.background = "red";
        document.addEventListener("touchmove", touchMove);
        document.addEventListener("touchend", touchEnd);
      }

      function touchMove(e) {
        e.preventDefault();
        movePosition(e.touches[0].clientX, e.touches[0].clientY);
        if (cnt == 0) {
          moving = setInterval(camMove, 50);
        }
        cnt++;
      }

      function touchEnd(e) {
        e.preventDefault();
        document.removeEventListener("touchmove", touchMove);
        document.removeEventListener("touchend", touchEnd);
        ball.style.background = "blue";
        ball.style.left = "50%";
        ball.style.top = "50%";
        ball.style.transform = "translate(-50%, -50%)";
        clearInterval(moving);
        cnt = 0;
      }

      function movePosition(posx, posy) {
        //ballの位置を設定
        ballCenterX = ball.getBoundingClientRect().left + ballRadius;
        ballCenterY = ball.getBoundingClientRect().top + ballRadius;
        let ballDist = Math.sqrt(
          Math.pow(ballCenterX - frameCenterX, 2) +
            Math.pow(ballCenterY - frameCenterY, 2)
        );
        let mouseDist = Math.sqrt(
          Math.pow(posx - frameCenterX, 2) + Math.pow(posy - frameCenterY, 2)
        );

        if (ballDist <= frameRadius && mouseDist < frameRadius) {
          ball.style.left = posx - shiftX + "px";
          ball.style.top = posy - shiftY + "px";
        } else {
          ballRad = Math.atan2(posy - frameCenterY, posx - frameCenterX);

          ball.style.left =
            frameRadius + frameRadius * Math.cos(ballRad) + "px";
          ball.style.top = frameRadius + frameRadius * Math.sin(ballRad) + "px";
        }
        //スピードを設定
        if (ballDist < frameRadius) {
          moveSpeed = (1 * ballDist) / frameRadius;
        } else {
          moveSpeed = 1;
        }
        //向きを設定
        ballRad = Math.atan2(
          ballCenterY - frameCenterY,
          ballCenterX - frameCenterX
        );
        if (ballRad != 0) {
          camRot = camera.getAttribute("rotation");
          direction = camRot.y - ((ballRad * 180) / Math.PI + 90);
          movex = -Math.sin((direction * Math.PI) / 180);
          movey = -Math.cos((-direction * Math.PI) / 180);
        } else {
          movex = 0;
          movey = 0;
        }
      }
      //カメラの移動
      var camMove = function () {
        camPos = camera.getAttribute("position");
        camera.setAttribute("position", {
          x: camPos.x + movex * moveSpeed,
          y: camPos.y,
          z: camPos.z + movey * moveSpeed,
        });
      };

自転

function planetRotate(planet,anglespeed){
  let rotation = planet.getAttribute("rotation"); 
  let angle=0;
  var rotate=function(){
    angle+=anglespeed;
    planet.setAttribute("rotation",{ x: 0, y: angle, z: 0});
  }
  setInterval(rotate, 100);
}

公転

function planetRevolve(planet,radius,speed){
  let angle = -speed;
  var move = function () {
    angle += speed;
    let radian = (angle * Math.PI) / 180;
    let z = Math.cos(radian) * radius;
    let x = Math.sin(radian) * radius;
    planet.setAttribute("position", { x: x, y: 0, z: z });
  };
  setInterval(move, 100);
}

参考までに地球のentityを

<a-entity
        id="erthrap"
        position="0 0 -25"
        rotation="0 0 -23.4" //地球の傾き
        scale="1 1 1"
      >
        <a-entity id="erth" gltf-model="#chikyu">
          <script>
            planetRotate(document.querySelector("#erth"), 1.53); //23.56秒で1週
          </script>
          <a-entity
            id="moon"
            position="0 0 1.3"
            rotation="0 0 -18.3"
            scale="0.272 0.272 0.272"
            gltf-model="#tuki"
          >
            <script>
              planetRevolve(document.querySelector("#moon"), 1.3, 0.055); //27.3日
              planetRotate(document.querySelector("#moon"), 0.055); //655.2秒で1週
            </script>
          </a-entity>
        </a-entity>
      </a-entity>

アップする前には何度もテストをしてるのですが
自分で作ったものは結局 予定調和なんでしょう
ちょっと反省
まぁ よくあることなのでちょっとだけです(笑)