source

마우스 "클릭"과 "클릭"

factcode 2022. 9. 11. 17:07
반응형

마우스 "클릭"과 "클릭"

용 i i i i를 쓴다.jQuery.click그래프에서 Raphael을 drag에는 「」, 「」가 있습니다.mousedown,mouseup ★★★★★★★★★★★★★★★★★」mousemove라파엘에서요

하기 click ★★★★★★★★★★★★★★★★★」dragclick또한 포함하다mousedown&mouseupJavascript에서는 마우스 클릭과 마우스 드래그 구별을 어떻게 해야 하나요?

점이 있다, 라는 게 것 요.mousemovemousedown ★★★★★★★★★★★★★★★★★」mouseup끌기는 하지만 클릭은 아닙니다.

다음과 같은 작업을 수행할 수 있습니다.

const element = document.createElement('div')
element.innerHTML = 'test'
document.body.appendChild(element)
let moved
let downListener = () => {
  moved = false
}
element.addEventListener('mousedown', downListener)
let moveListener = () => {
  moved = true
}
element.addEventListener('mousemove', moveListener)
let upListener = () => {
  if (moved) {
    console.log('moved')
  } else {
    console.log('not moved')
  }
}
element.addEventListener('mouseup', upListener)

// release memory
element.removeEventListener('mousedown', downListener)
element.removeEventListener('mousemove', moveListener)
element.removeEventListener('mouseup', upListener)

이러한 솔루션은 모두 마우스를 조금만 움직이면 중단되거나 지나치게 복잡해집니다.

다음은 2개의 이벤트 청취자를 사용한 간단한 적응형 솔루션입니다.델타는 코드를 클릭이 아닌 드래그로 분류하기 위해 상하로 상하로 이동해야 하는 픽셀 단위 거리입니다.그 이유는 마우스나 손가락을 들어올리기 전에 몇 픽셀씩 움직이기 때문입니다.

const delta = 6;
let startX;
let startY;

element.addEventListener('mousedown', function (event) {
  startX = event.pageX;
  startY = event.pageY;
});

element.addEventListener('mouseup', function (event) {
  const diffX = Math.abs(event.pageX - startX);
  const diffY = Math.abs(event.pageY - startY);

  if (diffX < delta && diffY < delta) {
    // Click!
  }
});

클리너 ES2015

let drag = false;

document.addEventListener('mousedown', () => drag = false);
document.addEventListener('mousemove', () => drag = true);
document.addEventListener('mouseup', () => console.log(drag ? 'drag' : 'click'));

다른 사람들이 말하는 것처럼 버그는 발생하지 않았다.

이미 jQuery를 사용하고 있는 경우:

var $body = $('body');
$body.on('mousedown', function (evt) {
  $body.on('mouseup mousemove', function handler(evt) {
    if (evt.type === 'mouseup') {
      // click
    } else {
      // drag
    }
    $body.off('mouseup mousemove', handler);
  });
});

이거 잘 될 거야.jQuery를 하지만 "jQuery"는 "jQuery"입니다.isDragging는 새 가 새새른른른른른른른른른른른른른른른른른 differs differs differs differs differs differs differs differs differs differs 의 위치와 다른 경우에만 리셋됩니다.mousedown 이 Chrome의 예: 벤트트 of)에서 작동합니다. 허용된 답변과 달리, 이는 Chrome의 최신 버전에서 작동합니다.mousemove마우스 이동 여부에 관계없이 실행됩니다.

var isDragging = false;
var startingPos = [];
$(".selector")
    .mousedown(function (evt) {
        isDragging = false;
        startingPos = [evt.pageX, evt.pageY];
    })
    .mousemove(function (evt) {
        if (!(evt.pageX === startingPos[0] && evt.pageY === startingPos[1])) {
            isDragging = true;
        }
    })
    .mouseup(function () {
        if (isDragging) {
            console.log("Drag");
        } else {
            console.log("Click");
        }
        isDragging = false;
        startingPos = [];
    });

.mousemove약간의 공차(즉, 작은 움직임을 드래그하지 않고 클릭으로 처리)를 추가하고 싶은 경우.

Rxjs를 사용하고 싶은 경우:

var element = document;

Rx.Observable
  .merge(
    Rx.Observable.fromEvent(element, 'mousedown').mapTo(0),
    Rx.Observable.fromEvent(element, 'mousemove').mapTo(1)
  )
  .sample(Rx.Observable.fromEvent(element, 'mouseup'))
  .subscribe(flag => {
      console.clear();
      console.log(flag ? "drag" : "click");
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/@reactivex/rxjs@5.4.1/dist/global/Rx.js"></script>

이는 @wong2가 답변에서 수행한 작업을 직접 복제한 것으로, RxJs로 변환한 것입니다.

의 흥미로운 사용법도 있습니다.sample는, 송신원으로부터 값( 「최신치」)을합니다.mergemousedown ★★★★★★★★★★★★★★★★★」mousemove가 관측 가능한 ).mouseup가 출력됩니다).가 방출됩니다.

mrjrdnthms가 수용된 답변에 대한 코멘트에서 지적했듯이, 이것은 더 이상 Chrome에서는 동작하지 않습니다(마우스 이동을 항상 기동합니다). 나는 Chrome 동작에 대처하기 위해 Gustavo의 답변을 수정했습니다(jQuery를 사용하고 있기 때문에).

var currentPos = [];

$(document).on('mousedown', function (evt) {

   currentPos = [evt.pageX, evt.pageY]

  $(document).on('mousemove', function handler(evt) {

    currentPos=[evt.pageX, evt.pageY];
    $(document).off('mousemove', handler);

  });

  $(document).on('mouseup', function handler(evt) {

    if([evt.pageX, evt.pageY].equals(currentPos))
      console.log("Click")
    else
      console.log("Drag")

    $(document).off('mouseup', handler);

  });

});

Array.prototype.equals함수는 이 답변에서 비롯됩니다.

정말 이렇게 간단해

var dragged = false
window.addEventListener('mousedown', function () { dragged = false })
window.addEventListener('mousemove', function () { dragged = true })
window.addEventListener('mouseup', function() {
        if (dragged == true) { return }
        console.log("CLICK!! ")
})

정말로 작은 이동을 허용하는 임계값을 추가하고 싶지 않습니다.위의 내용은 모든 데스크톱인터페이스를 클릭했을 때의 올바른 정상적인 느낌입니다.

한번 해봐.

원하는 경우 이벤트를 쉽게 추가할 수 있습니다.

5픽셀 x/y의 jQuery를 사용하여 드래그 검출:

var dragging = false;
$("body").on("mousedown", function(e) {
  var x = e.screenX;
  var y = e.screenY;
  dragging = false;
  $("body").on("mousemove", function(e) {
    if (Math.abs(x - e.screenX) > 5 || Math.abs(y - e.screenY) > 5) {
      dragging = true;
    }
  });
});
$("body").on("mouseup", function(e) {
  $("body").off("mousemove");
  console.log(dragging ? "drag" : "click");
});

다음과 같이 할 수 있습니다.

var div = document.getElementById("div");
div.addEventListener("mousedown", function() {
  window.addEventListener("mousemove", drag);
  window.addEventListener("mouseup", lift);
  var didDrag = false;
  function drag() {
    //when the person drags their mouse while holding the mouse button down
    didDrag = true;
    div.innerHTML = "drag"
  }
  function lift() {
    //when the person lifts mouse
    if (!didDrag) {
      //if the person didn't drag
      div.innerHTML = "click";
    } else div.innerHTML = "drag";
    //delete event listeners so that it doesn't keep saying drag
    window.removeEventListener("mousemove", drag)
    window.removeEventListener("mouseup", this)
  }
})
body {
  outline: none;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: Arial, Helvetica, sans-serif;
  overflow: hidden;
}
#div {
  /* calculating -5px for each side of border in case border-box doesn't work */
  width: calc(100vw - 10px);
  height: calc(100vh - 10px);
  border: 5px solid orange;
  background-color: yellow;
  font-weight: 700;
  display: grid;
  place-items: center;
  user-select: none;
  cursor: pointer;
  padding: 0;
  margin: 0;
}
<html>
  <body>
    <div id="div">Click me or drag me.</div>
  </body>
</html>

드래그 케이스를 필터링 하는 경우는, 다음과 같이 실시합니다.

var moved = false;
$(selector)
  .mousedown(function() {moved = false;})
  .mousemove(function() {moved = true;})
  .mouseup(function(event) {
    if (!moved) {
        // clicked without moving mouse
    }
  });

거리 임계값을 사용하는 클래스 기반 바닐라 JS의 또 다른 솔루션

private initDetectDrag(element) {
    let clickOrigin = { x: 0, y: 0 };
    const dragDistanceThreshhold = 20;

    element.addEventListener('mousedown', (event) => {
        this.isDragged = false
        clickOrigin = { x: event.clientX, y: event.clientY };
    });
    element.addEventListener('mousemove', (event) => {
        if (Math.sqrt(Math.pow(clickOrigin.y - event.clientY, 2) + Math.pow(clickOrigin.x - event.clientX, 2)) > dragDistanceThreshhold) {
            this.isDragged = true
        }
    });
}

클래스 내부에 추가합니다(SOMESLIDER_ELEment는 글로벌하게 문서화할 수도 있습니다).

private isDragged: boolean;
constructor() {
    this.initDetectDrag(SOMESLIDER_ELEMENT);
    this.doSomeSlideStuff(SOMESLIDER_ELEMENT);
    element.addEventListener('click', (event) => {
        if (!this.sliderIsDragged) {
            console.log('was clicked');
        } else {
            console.log('was dragged, ignore click or handle this');
        }
    }, false);
}

최근 사용자가 항목을 클릭하거나 끌 수 있는 트리 목록에서 동일한 문제가 발생하여 이 크기를 줄였습니다.Pointer수업하고 내 안에 넣어.utils.js

function Pointer(threshold = 10) {
  let x = 0;
  let y = 0;

  return {
    start(e) {
     x = e.clientX;
     y = e.clientY;
    },

    isClick(e) {
      const deltaX = Math.abs(e.clientX - x);
      const deltaY = Math.abs(e.clientY - y);
      return deltaX < threshold && deltaY < threshold;
    }
  }
}

여기 직장에서 볼 수 있습니다.

function Pointer(threshold = 10) {
  let x = 0;
  let y = 0;

  return {
    start(e) {
     x = e.clientX;
     y = e.clientY;
    },

    isClick(e) {
      const deltaX = Math.abs(e.clientX - x);
      const deltaY = Math.abs(e.clientY - y);
      return deltaX < threshold && deltaY < threshold;
    }
  }
}

const pointer = new Pointer();

window.addEventListener('mousedown', (e) => pointer.start(e))
//window.addEventListener('mousemove', (e) => pointer.last(e))
window.addEventListener('mouseup', (e) => {
  const operation = pointer.isClick(e) 
    ? "Click"
    : "Drag"
  console.log(operation)
})

순수 JS(DeltaX 및 Delta 포함)y

이 DeltaX 및 DeltaY는 승인된 답변의 코멘트에 의해 제시된 바와 같이 클릭해서 드래그 조작을 하려고 할 때 불편함을 피할 수 있습니다.

    deltaX = deltaY = 2;//px
    var element = document.getElementById('divID');
    element.addEventListener("mousedown", function(e){
        if (typeof InitPageX == 'undefined' && typeof InitPageY == 'undefined') {
            InitPageX = e.pageX;
            InitPageY = e.pageY;
        }

    }, false);
    element.addEventListener("mousemove", function(e){
        if (typeof InitPageX !== 'undefined' && typeof InitPageY !== 'undefined') {
            diffX = e.pageX - InitPageX;
            diffY = e.pageY - InitPageY;
            if (    (diffX > deltaX) || (diffX < -deltaX)
                    || 
                    (diffY > deltaY) || (diffY < -deltaY)   
                    ) {
                console.log("dragging");//dragging event or function goes here.
            }
            else {
                console.log("click");//click event or moving back in delta goes here.
            }
        }
    }, false);
    element.addEventListener("mouseup", function(){
        delete InitPageX;
        delete InitPageY;
    }, false);

   element.addEventListener("click", function(){
        console.log("click");
    }, false);

OSM 맵에서의 공개 액션(클릭 시 마커의 위치 설정)에 대해서는, 1) 마우스의 다운 > 업의 지속 시간을 결정하는 방법(클릭 시마다 새로운 마커를 작성하는 것은 상상할 수 없다), 및 2) 마우스가 다운 > 업중에 이동했는지(사용자가 지도를 드래그 하고 있다)가 문제였습니다.

const map = document.getElementById('map');

map.addEventListener("mousedown", position); 
map.addEventListener("mouseup", calculate);

let posX, posY, endX, endY, t1, t2, action;

function position(e) {

  posX = e.clientX;
  posY = e.clientY;
  t1 = Date.now();

}

function calculate(e) {

  endX = e.clientX;
  endY = e.clientY;
  t2 = (Date.now()-t1)/1000;
  action = 'inactive';

  if( t2 > 0.5 && t2 < 1.5) { // Fixing duration of mouse down->up

      if( Math.abs( posX-endX ) < 5 && Math.abs( posY-endY ) < 5 ) { // 5px error on mouse pos while clicking
         action = 'active';
         // --------> Do something
      }
  }
  console.log('Down = '+posX + ', ' + posY+'\nUp = '+endX + ', ' + endY+ '\nAction = '+ action);    

}

이 답변을 바탕으로 React 컴포넌트로 다음과 같이 했습니다.

export default React.memo(() => {
    const containerRef = React.useRef(null);

    React.useEffect(() => {
        document.addEventListener('mousedown', handleMouseMove);

        return () => document.removeEventListener('mousedown', handleMouseMove);
    }, []);

    const handleMouseMove = React.useCallback(() => {
        const drag = (e) => {
            console.log('mouse is moving');
        };

        const lift = (e) => {
            console.log('mouse move ended');
            window.removeEventListener('mousemove', drag);
            window.removeEventListener('mouseup', this);
        };

        window.addEventListener('mousemove', drag);
        window.addEventListener('mouseup', lift);
    }, []);

    return (
        <div style={{ width: '100vw', height: '100vh' }} ref={containerRef} />
    );
})

특정 요소의 클릭 또는 끌기 동작을 확인하려면 본문을 들을 필요 없이 이 작업을 수행할 수 있습니다.

$(document).ready(function(){
  let click;
  
  $('.owl-carousel').owlCarousel({
    items: 1
  });
  
  // prevent clicks when sliding
  $('.btn')
    .on('mousemove', function(){
      click = false;
    })
    .on('mousedown', function(){
      click = true;
    });
    
  // change mouseup listener to '.content' to listen to a wider area. (mouse drag release could happen out of the '.btn' which we have not listent to). Note that the click will trigger if '.btn' mousedown event is triggered above
  $('.btn').on('mouseup', function(){
    if(click){
      $('.result').text('clicked');
    } else {
      $('.result').text('dragged');
    }
  });
});
.content{
  position: relative;
  width: 500px;
  height: 400px;
  background: #f2f2f2;
}
.slider, .result{
  position: relative;
  width: 400px;
}
.slider{
  height: 200px;
  margin: 0 auto;
  top: 30px;
}
.btn{
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  height: 100px;
  background: #c66;
}
.result{
  height: 30px;
  top: 10px;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.min.css" />
<div class="content">
  <div class="slider">
    <div class="owl-carousel owl-theme">
      <div class="item">
        <a href="#" class="btn" draggable="true">click me without moving the mouse</a>
      </div>
      <div class="item">
        <a href="#" class="btn" draggable="true">click me without moving the mouse</a>
      </div>
    </div>
    <div class="result"></div>
  </div>
  
</div>

@Przemek의 답변에서

function listenClickOnly(element, callback, threshold=10) {
  let drag = 0;
  element.addEventListener('mousedown', () => drag = 0);
  element.addEventListener('mousemove', () => drag++);
  element.addEventListener('mouseup', e => {
    if (drag<threshold) callback(e);
  });
}

listenClickOnly(
  document,
  () => console.log('click'),
  10
);

다음 코딩은 의 움직임을 감지하기 위한 것입니다.mouseup그리고.mousedown.

대부분의 경우에 효과가 있을 것이다.치료 방법에 따라 다르기도 합니다.mouseevent클릭해서.

JavaScript에서는 검출이 매우 간단합니다.마우스 다운과 마우스 업 사이의 누름 시간이나 이동 시간은 중요하지 않습니다. Event.detail마우스를 이동해도 1로 리셋되지 않습니다.mousedown그리고.mouseup.

클릭과 길게 누르는 것을 구별해야 하는 경우,event.timeStamp너무.

// ==== add the code at the begining of your coding ====
let clickStatus = 0;
(() => {
    let screenX, screenY;
    document.addEventListener('mousedown', (event) => ({screenX, screenY} = event), true); 
    document.addEventListener('mouseup', (event) => (clickStatus = Math.abs(event.screenX - screenX) + Math.abs(event.screenY - screenY) < 3), true);
})();
// ==== add the code at the begining of your coding ====

$("#draggable").click(function(event) {
    if (clickStatus) {
        console.log(`click event is valid, click count: ${event.detail}`)
    } else {
        console.log(`click event is invalid`)
    }

})
<!doctype html>
<html lang="en">
<!-- coding example from https://jqueryui.com/draggable/ -->
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Draggable - Default functionality</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <style>
  #draggable { width: 150px; height: 150px; padding: 0.5em; }
  </style>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $( "#draggable" ).draggable();
  } );
  </script>
</head>
<body>
 
<div id="draggable" class="ui-widget-content">
  <p>Drag me around</p>
</div>
 
 
</body>
</html>

언급URL : https://stackoverflow.com/questions/6042202/how-to-distinguish-mouse-click-and-drag

반응형