最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to handle hybrid devices in clicktouch events properly? - Stack Overflow

programmeradmin5浏览0评论

I'm trying to find out how to work with hybrid devices when it es to binding touch and click events, but I can't find any solution that actually seems to work (I haven't got a hybrid device so I cannot test directly but since the failed attempts doesn't even work on normal devices I assume they don't work on a hybrid device either).

The problem is that on a hybrid device you have to cover both touch and click events without firing the functions twice. So if you look at my failed attempts (2 and 3) you can see that I bind to both touchend and click, but there appears to be some sort of syntax error or something because this causes none of the events to actually fire.

The first solution works fine but that's when I'm just using one or the other of the event firing types.

What I've tried so far:

1 - Works on touch devices and click devices:

_renderer.listenGlobal('document', 'ontouchstart' in window ? 'touchend' : 'click', (e) => {

  console.log('works');  
});

2 - Doesn't fire on either touch or click devices:

_renderer.listenGlobal('document', 'touchend click', (e) => {

  console.log('works');

  e.stopPropagation(); 
});

3 - Doesn't fire on either touch or click devices:

_renderer.listenGlobal('document', 'touchend, click', (e) => {

  console.log('works');  

  e.stopPropagation();
});

As you can see the first example covers 2/3 device types, while the other ones cover 0.

How can I make sure that my functions will run properly on every device?

I'm trying to find out how to work with hybrid devices when it es to binding touch and click events, but I can't find any solution that actually seems to work (I haven't got a hybrid device so I cannot test directly but since the failed attempts doesn't even work on normal devices I assume they don't work on a hybrid device either).

The problem is that on a hybrid device you have to cover both touch and click events without firing the functions twice. So if you look at my failed attempts (2 and 3) you can see that I bind to both touchend and click, but there appears to be some sort of syntax error or something because this causes none of the events to actually fire.

The first solution works fine but that's when I'm just using one or the other of the event firing types.

What I've tried so far:

1 - Works on touch devices and click devices:

_renderer.listenGlobal('document', 'ontouchstart' in window ? 'touchend' : 'click', (e) => {

  console.log('works');  
});

2 - Doesn't fire on either touch or click devices:

_renderer.listenGlobal('document', 'touchend click', (e) => {

  console.log('works');

  e.stopPropagation(); 
});

3 - Doesn't fire on either touch or click devices:

_renderer.listenGlobal('document', 'touchend, click', (e) => {

  console.log('works');  

  e.stopPropagation();
});

As you can see the first example covers 2/3 device types, while the other ones cover 0.

How can I make sure that my functions will run properly on every device?

Share Improve this question asked Oct 8, 2016 at 9:19 ChrillewoodzChrillewoodz 28.3k23 gold badges99 silver badges186 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 9 +100

You could use a Subject and debounce for a couple of milliseconds so you only have one event, something like this:

import {Component, Renderer} from '@angular/core'
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
    </div>
  `,
})
export class App {
  name = 'Angular2';
  subject = new Subject();
  
  constructor(renderer: Renderer) {
    renderer.listenGlobal('document', 'touchend', (e) => {
      console.log('touchend');
      this.subject.next(e);
    });
    renderer.listenGlobal('document', 'click', (e) => {
      console.log('click');
      this.subject.next(e);
    });

    this.subject.debounceTime(100).subscribe(event => {
      console.log(event); //do stuff here
    })
  }
}

So when you use hybrid devices, you will get this:

Two events were fired, but you only get one on your Observable.

You can play around in this plunker

Just add (tap) directive instead of (click) directive on your ponents and add hammerjs to your index.html file.

Angular 2 will do all the job for you.

Example:

<my-ponent (tap)="doSomething()"></my-ponent>

On your index.html add:

<script src="hammer.min.js"></script>

To get hammerjs

npm install hammerjs --save

With this the click and the tap will work fine. If you want to have more control over the tap or you want to bind events to your element on runtime try something like this.

_hammerEvents: HammerManager;

public bindTapEvent(element: ElementRef):void{
    this._hammerEvents = new Hammer(element.nativeElement);
    this._hammerEvents.on("tap", (event:any) => { /* do something */});
}
发布评论

评论列表(0)

  1. 暂无评论