回答:
私は差があるということだと思うmousemove
の間mousedown
と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)
mousedown
とmouseup
代わりに聴取のmousemove
フラグを設定するイベントを。さらに、@ mrjrdnthmsによって言及された問題を修正します
すでに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);
});
});
drag
。他のコメントのような追加のスコープがここで必要になるかもしれないと言っています。
evt
、2番目の位置と比較することevt
ですif (evt.type === 'mouseup' || Math.abs(evt1.pageX - evt2.pageX) < 5 || Math.abs(evt1.pageY - evt2.pageY) < 5) { ...
。たとえば、次のようになります。
.on('mouseup mousemove touchend touchmove')
あり、その上に位置変数を設定していません。素晴らしい解決策!
let drag = false;
document.addEventListener('mousedown', () => drag = false);
document.addEventListener('mousemove', () => drag = true);
document.addEventListener('mouseup', () => console.log(drag ? 'drag' : 'click'));
他のコメントどおり、バグは発生していません。
これはうまくいくはずです。受け入れられた回答に似ています(ただしjQueryを使用します)。ただし、isDragging
フラグは、新しいマウスの位置がmousedown
イベントの位置と異なる場合にのみリセットされます。承認された回答とは異なり、これは最近のバージョンの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
少し許容範囲を追加する場合は、座標チェックインを調整することもできます(つまり、小さな動きをドラッグではなくクリックとして扱います)。
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が彼の回答で行ったことの直接のクローンですが、RxJに変換されています。
の興味深い使用法sample
。sample
オペレータは、(ソースから最新の値を取るmerge
のmousedown
とmousemove
)とするとき、内側観察(それを放出するmouseup
)を発します。
mrjrdnthmsが承認された回答に関するコメントで指摘しているように、これはChromeでは機能しなくなり(常にマウスムーブが発生します)、Chromeの動作に対処するために(jQueryを使用しているため)Gustavoの回答を調整しました。
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
この関数は、このから来ている答え
[evt.pageX, evt.pageY].equals()
コマンドからエラーが発生しました。私はそれをに置き換え(evt.pageX === currentPos[0] && evt.pageY===currentPos[1])
、すべてが良かった。:)
equals
私の記事の下部にあるリンクから追加するコードの必要性
currentPos
するのmousemove
ですか?これは、ドラッグをクリックとして扱うことを意味するのではないですか?
"mouseup"
まだマウスを動かしている間は、これは発生しません。
これらのソリューションはすべて、小さなマウスの動きを妨げるか、過度に複雑です。
これは、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!
}
});
delta
これに何が使われているのかわかりますか?それはモバイルデバイスのタップと関係がありますか?
delta
、「1クリックのマウス移動により、クリックしてドラッグ操作を実行しようとするとイライラする」
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 moved = false;
$(selector)
.mousedown(function() {moved = false;})
.mousemove(function() {moved = true;})
.mouseup(function(event) {
if (!moved) {
// clicked without moving mouse
}
});
このDeltaXとDeltaYは、1ティックのマウス移動によるクリック操作とドラッグ操作を取得しようとするときにイライラするエクスペリエンスを回避するために、承認された回答のコメントで提案されています。
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);
}
クラスベースのバニラ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);
}
特定の要素のクリックまたはドラッグの動作を確認する場合は、本体を聞く必要なしにこれを行うことができます。
$(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
);