admin管理员组文章数量:1287790
Click event is working fine when using mouse with puter. Even when I put mouse button down on button move cursor and then release mouse button inside button area, click event is firing. But same with touchscreen it is not working. I know that reason is that in touchscreen that kind of dragging is considered as scrolling. Click event is fired when I don't move finger too much on button. So only down and up without moving. My client has problem that they are moving finger too much and it is too hard to get click event. Is it possible to set bigger threshold for how much finger can move that it is still considered as click and not scroll?
I found this article where touch events are handled byself and translated them to click event. .html I would not to like to go this road.
Have you any suggestion how can I solve this?
Here is more detail about touch events Look at Handling clicks there is described how click is working in touchscreens. Still I didn't managed to work. Few months ago I but evt.preventDefault();
to my touchmove event handler and it did fix problem but currently it seems not.
EDIT:2019.11.5
Here is what was working earlier but no anymore:
html
<body (touchmove)="touchMoveEvent($event)"></body>
TypeScript
touchMoveEvent(ev: Event): void
{
ev.preventDefault();
}
And here is basic angular example of button and click handler which is not working if user is moving finger too much. I haven't check what is threshold but my I assume it is something near 10px-20px.
<button (click)="onClickEventHandler($event)">Press button</button>
onClickEventHandler(ev: Event) {
//do the thing here
}
I have tested touchscreen functionality with chrome's devtools toggle device toolbar.
Click event is working fine when using mouse with puter. Even when I put mouse button down on button move cursor and then release mouse button inside button area, click event is firing. But same with touchscreen it is not working. I know that reason is that in touchscreen that kind of dragging is considered as scrolling. Click event is fired when I don't move finger too much on button. So only down and up without moving. My client has problem that they are moving finger too much and it is too hard to get click event. Is it possible to set bigger threshold for how much finger can move that it is still considered as click and not scroll?
I found this article where touch events are handled byself and translated them to click event. http://phonegap-tips./articles/fast-touch-event-handling-eliminate-click-delay.html I would not to like to go this road.
Have you any suggestion how can I solve this?
Here is more detail about touch events https://developer.mozilla/en-US/docs/Web/API/Touch_events Look at Handling clicks there is described how click is working in touchscreens. Still I didn't managed to work. Few months ago I but evt.preventDefault();
to my touchmove event handler and it did fix problem but currently it seems not.
EDIT:2019.11.5
Here is what was working earlier but no anymore:
html
<body (touchmove)="touchMoveEvent($event)"></body>
TypeScript
touchMoveEvent(ev: Event): void
{
ev.preventDefault();
}
And here is basic angular example of button and click handler which is not working if user is moving finger too much. I haven't check what is threshold but my I assume it is something near 10px-20px.
<button (click)="onClickEventHandler($event)">Press button</button>
onClickEventHandler(ev: Event) {
//do the thing here
}
I have tested touchscreen functionality with chrome's devtools toggle device toolbar.
Share Improve this question edited Nov 5, 2019 at 20:19 Janne Harju asked Oct 29, 2019 at 16:06 Janne HarjuJanne Harju 1,1711 gold badge16 silver badges30 bronze badges 3- 3 Add your code please – Vo Kim Nguyen Commented Nov 1, 2019 at 5:05
- is it solved ? if not please add code – 0xAnon Commented Nov 1, 2019 at 5:23
- No its not solved yet. I Will add some code later when I get on my puter. – Janne Harju Commented Nov 2, 2019 at 14:34
6 Answers
Reset to default 6 +50Here is a nice solution. by using the touchstart
and touchend
events you can measure the distance between the 2 points and fire a click event if the events where close (in terms of pixels). read my ments.
class ScrollToClick {
constructor(elem, maxDistance = 20) {
this.elem = elem;
this.start = null;
this.maxDistance = maxDistance;
// Bind the touches event to the element
this.bindTouchEvents();
}
bindTouchEvents() {
this.elem.addEventListener('touchstart', this.onTouchStart.bind(this), false);
this.elem.addEventListener('touchend', this.onTouchEnd.bind(this), false);
}
onTouchStart(e) {
// hold the touch start position
this.start = e.touches[0];
// clear the position after 2000 mil (could be set for less).
setTimeout(() => { this.start = null; }, 2000);
}
onTouchEnd(e) {
// if the timeout was called, there will be no start position
if (!this.start) { return; }
// calculate the distance between start and end position
const end = e.changedTouches[0],
dx = Math.pow(this.start.pageX - end.pageX, 2),
dy = Math.pow(this.start.pageY - end.pageY, 2),
distance = Math.round(Math.sqrt(dx + dy));
// if the distance is fairly small, fire
// a click event. (default is 20 but you can override it through the constructor)
if (distance <= this.maxDistance) {
this.elem.click();
}
// clear the start position again
this.start = null;
}
}
Then you can use it with any element like so:
// use any element you wish (here I'm using the body)
const elem = document.body;
// initialize the class with the given element
new ScrollToClick(elem);
// listen to a click event on this element.
elem.addEventListener('click', (e) => {
console.log('Clicked');
})
My final solution is here. I forgot to mention in text that I am using Angular although I but in tag.
So I made Angular directive and but in AfikDeri's suggestion which was really close with directive style code.
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
@Directive({
selector: '[touchClick]'
})
export class TouchClickDirective implements OnInit {
@Input() maxDistance = 100;
@Input() maxTime = 2000;
@Input() touchClick: boolean;
start: Touch;
constructor(private elem: ElementRef) {
this.start = null;
}
ngOnInit(): void {
// Bind the touches event to the element
this.bindTouchEvents();
}
bindTouchEvents() {
this.elem.nativeElement.addEventListener('touchstart', this.onTouchStart.bind(this), false);
this.elem.nativeElement.addEventListener('touchend', this.onTouchEnd.bind(this), false);
}
onTouchStart(e: TouchEvent) {
// hold the touch start position
this.start = e.touches[0];
// clear the position after 2000 mil (could be set for less).
setTimeout(() => {
this.start = null;
}, this.maxTime);
}
onTouchEnd(e: TouchEvent) {
// if the timeout was called, there will be no start position
if (!this.start) {
return;
}
// calculate the distance between start and end position
const end = e.changedTouches[0],
dx = Math.pow(this.start.pageX - end.pageX, 2),
dy = Math.pow(this.start.pageY - end.pageY, 2),
distance = Math.round(Math.sqrt(dx + dy));
// if the distance is fairly small, fire
// a click event. (default is 20 but you can override it through the constructor)
if (distance <= this.maxDistance) {
this.elem.nativeElement.click();
}
// clear the start position again
this.start = null;
}
}
And here is how it can be used
<button mat-flat-button [touchClick] [maxDistance]="100" [maxTime]="300" (click)="doWarning()">
Generate Warning
</button>
This is a GitHub Issue that seems to be similar. I am not a JS dev so I am not sure but hope this helps.
I worked out a quick solution to this problem based only on external value state set on different event listeners. Btn click fn will be triggered on touchend event if moveState variable will not change value by touchmove event. Touch start is always resetting state.
const moveState = false;
btn.addEventListener("click", (e) => handleBtnClick(e));
btn.addEventListener("touchstart", (e) => handleBtnTouchStart(e));
btn.addEventListener("touchmove", (e) => handleBtnTouchMove(e));
btn.addEventListener("touchend", (e) => handleBtnClick(e));
function handleHotspotTouchStart(e){
moveState = false;
}
function handleHotspotTouchMove(e){
moveState = true;
}
function handleBtnClick(e){
e.preventDefault;
if(e.type === 'touchend'){
if(moveState) return;
}
// trigger btn click action for both cursor click and touch if no movement detected
btnClick();
}
To add to the accepted answer, here is my react implementation:
import React, { useState } from 'react';
import './Button.css';
interface ButtonProps {
className: string,
value: string,
icon?: string,
onClick: () => void,
onPointerDown?: () => void,
onPointerUp?: () => void,
style?: React.CSSProperties,
}
function Button(props: ButtonProps): JSX.Element {
const [touchStart, setTouchStart] = useState(null);
const onTouchStart = (e) => {
// store the touchStart position
setTouchStart(e.touches[0]);
// clear the position after 2000ms
setTimeout(() => setTouchStart(null), 2000);
};
const onTouchEnd = (e) => {
// if the timeout was called, there will be no touchStart position
if (!touchStart) return;
// calculate the distance between touchStart and touchEnd position
const touchEnd = e.changedTouches[0],
dx = Math.pow(touchStart.pageX - touchEnd.pageX, 2),
dy = Math.pow(touchStart.pageY - touchEnd.pageY, 2),
distance = Math.round(Math.sqrt(dx + dy));
// if the distance is fairly small, fire a click event.
if (distance <= 50 && distance > 5) {
props.onClick();
}
// clear the start position again
setTouchStart(null);
};
return (
<button
className={`${props.className}`}
onClick={props.onClick}
onPointerDown={props.onPointerDown}
onPointerUp={props.onPointerUp}
onTouchStart={onTouchStart}
onTouchEnd={onTouchEnd}
style={props.style}
>
{props.icon ? <img className="button__icon" src={props.icon} alt=""/> : ''}
{props.value}
</button>
);
}
export default Button;
you can use (mousedown) event instead of (click) that will work.
本文标签: javascriptClick event not firing on touchscreen when finger moves a bitStack Overflow
版权声明:本文标题:javascript - Click event not firing on touchscreen when finger moves a bit - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741282906a2370110.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论