Frontend/Three.js

Raycaster, 드래그 클릭 방지

wam 2024. 11. 25. 15:45

 

드래그 클릭 방지

  • 드래그 후 마우스를 떼는 순간 클릭됐다 체크된다.
  • 마우스 이벤트를 사용하여 드래그 클릭 방지하기

 

 

처음 위치에서 최소 거리 이상 이동 시 드래그로 간주

function checkIntersects() {
  if (mouseDragMoved) return; // 드래그 시 클릭 이벤트 실행하지 않음

  // 카메라와 마우스 위치를 사용해 Raycaster 업데이트
  raycaster.setFromCamera(mouse, camera);

  // 마우스 위치와 교차하는 객체 확인
  const intersects = raycaster.intersectObjects(meshes);
  for (const item of intersects) {
    console.log("📢 [ex03_preventDragClick.js:85]", item.object.name);

    // 색상이 이미 빨간색인지 확인
    if (item.object.material.color.equals(new THREE.Color("red"))) {
      // 빨간색이면 원래 색상으로 변경
      item.object.material.color.copy(item.object.originalColor);
    } else {
      // 원래 색상이면 빨간색으로 변경
      item.object.material.color.set("red");
    }
    break; // 첫 번째 교차한 객체만 처리
  }
}

// 드래그 클릭 방지
let mouseDragMoved; // 마우스를 드래그 여부 체크
let clickStartX;
let clickStartY;

canvas.addEventListener("mousedown", (e) => {
  // 처음 클릭한 위치 좌표
  clickStartX = e.clientX;
  clickStartY = e.clientY;
});

canvas.addEventListener("mouseup", (e) => {
  // 마우스를 클릭하는 위치와 마우스를 떼는 시점의 위치가 일정 거리 차이가 있다면 드래그 한 것으로 간주
  const xGap = Math.abs(e.clientX - clickStartX);
  const yGap = Math.abs(e.clientY - clickStartY);
	
	const dragThreshold = 5; // 드래그로 간주할 최소 거리
  if (xGap > dragThreshold || yGap > dragThreshold) {
    // 드래그로 간주
    mouseDragMoved = true;
  } else {
    mouseDragMoved = false;
  }
});

위에서 문제점은 드래그로 회전했다 원래 위치로 돌아갔을 경우 최소 이동거리 내로 체크될 경우가 있다. 이는 특정시간으로 체크하여 드래그로 간주해주어야 한다.

 

 

절대값 함수

Math.abs(-5);  // 결과: 5
Math.abs(3);   // 결과: 3

 

 

경과 시간으로 드래그 간주

canvas.addEventListener("mouseup", (e) => {
  // 마우스를 클릭하는 위치와 마우스를 떼는 시점의 위치가 일정 거리 차이가 있다면 드래그 한 것으로 간주
  const xGap = Math.abs(e.clientX - clickStartX);
  const yGap = Math.abs(e.clientY - clickStartY);
  const timeGap = Date.now() - clickStartTime;

  const dragThreshold = 5; // 드래그로 간주할 최소 거리
  const dragThresholdTime = 500; // 드래그로 간주할 최소 시간 (단위: 밀리초) 0.5초
  if (
    xGap > dragThreshold ||
    yGap > dragThreshold ||
    timeGap > dragThresholdTime
  ) {
    // 드래그로 간주
    mouseDragMoved = true;
  } else {
    mouseDragMoved = false;
  }
});