在 Angular2 中使用移动事件
Using mobile events in Angular2
我想知道是否可以获得有关移动设备事件的帮助。我正在寻找一种方法来将函数绑定到 Angular 2 中的滑动事件。我在 Github 上的 this issue 中看到提到 Angular 2 使用 Hammer.js 用于移动事件处理。
我在使事件正常运行时遇到了一些问题,因为我收到以下错误:
EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event
我的代码片段如下:
import {Component, View, AfterContentInit} from 'angular2/core';
import {HelperService} from "./helper-service";
import {HammerGesturesPluginCommon} from 'angular2/src/platform/dom/events/hammer_common'
@View({
template: `<div [id]="middleCircle" (swipeleft)="doThis()"></div>`
})
export class ColumnDirective implements AfterContentInit {
constructor(private helperService:HelperService) {}
doThis(){
console.log('This thing has been done.');
}
}
如果我将 Hammer Gestures 添加到我的构造函数中,我会收到此错误:
constructor(private helperService:HelperService, private hammerGesturesPluginCommon: HammerGesturesPluginCommon) {}
EXCEPTION: No provider for t! (ColumnDirective -> t)
任何有关此问题的帮助将不胜感激!
您需要添加
HelperService
和 HammerGesturesPluginCommon
到某处的提供者,在 @Component(...)
注释中或在 bootstrap(AppComponent, [...])
中以消除错误 "No provider for ..."
您是否在入口页面的某处添加了 Hammer.js
的脚本标签?
我能够绕过内置的 Hammer 集成和 运行 我自己的集成:
import { Component, ElementRef, AfterViewInit } from 'angular2/core';
@Component({
selector: 'redeem',
templateUrl: './redeem/components/redeem.html'
})
export class RedeemCmp implements AfterViewInit {
static hammerInitialized = false;
constructor(private el:ElementRef) { }
ngAfterViewInit() {
console.log('in ngAfterViewInit');
if (!RedeemCmp.hammerInitialized) {
console.log('hammer not initialised');
var myElement = document.getElementById('redeemwrap');
var hammertime = new Hammer(myElement);
hammertime.on('swiperight', function(ev) {
console.log('caught swipe right');
console.log(ev);
});
RedeemCmp.hammerInitialized = true;
} else {
console.log('hammer already initialised');
}
}
}
经过大量尝试,我没有成功让 Angular2 的 HammerGesturesPluginCommon 工作(到目前为止)。受 Bill Mayes 回答的启发,我将此作为对他的回答的详细说明提交,我能够开始工作(在 Ipad mini 和 Android phone 上测试)。
基本上,我的解决方案如下。
首先,在你的 index.html 文件的脚本标签中手动引用 hammer.js(我还引用了 hammer-time 来消除 300 毫秒的延迟):
其次,安装 hammerjs 的类型定义(tsd install hammerjs -save)。然后你可以像这样创建一个 Angular2 attibute 指令:
/// <reference path="./../../../typings/hammerjs/hammerjs.d.ts" />
import {Directive, ElementRef, AfterViewInit, Output, EventEmitter} from 'angular2/core';
@Directive({
selector: '[hammer-gestures]'
})
export class HammerGesturesDirective implements AfterViewInit {
@Output() onGesture = new EventEmitter();
static hammerInitialized = false;
constructor(private el: ElementRef) {
}
ngAfterViewInit() {
if (!HammerGesturesDirective.hammerInitialized) {
let hammertime = new Hammer(this.el.nativeElement);
hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
hammertime.on("swipeup", (ev) => {
this.onGesture.emit("swipeup");
});
hammertime.on("swipedown", (ev) => {
this.onGesture.emit("swipedown");
});
hammertime.on("swipeleft", (ev) => {
this.onGesture.emit("swipeleft");
});
hammertime.on("swiperight", (ev) => {
this.onGesture.emit("swiperight");
});
hammertime.on("tap", (ev) => {
this.onGesture.emit("tap");
});
HammerGesturesDirective.hammerInitialized = true;
}
}
}
你需要设置Hammer.DIRECTION_ALL如果你想检测垂直(up/down)滑动(left/right滑动是默认的,不是垂直的).可以在此处找到有关锤子 api 的更多选项:http://hammerjs.github.io/api/#hammer
最后,在你的父组件中你可以做这样的事情:
import {Component} from "angular2/core";
import {HammerGesturesDirective} from "./path/HammerGesturesDirective";
@Component({
selector: "my-ng2-component",
template: `<div style='width:100px; height: 100px;background-color: red'
(onGesture)="doSwipe($event)" hammer-gestures></div>`,
directives: [HammerGesturesDirective]
})
export class MyNg2Component {
constructor() { }
doSwipe(direction: string) {
alert(direction);
}
}
这样,当您想在任何特定元素上启用锤子手势时,您只需要引用属性 hammer-gestures。 注意:该元素似乎需要一个唯一的 ID 才能工作。
我有点犹豫要不要在我的应用程序中添加滑动手势,因为这里的答案似乎暗示它会有点乱。
EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event
只需加载 hammer.js 即可轻松解决此错误。无需自定义代码。
评论中提到的另一个错误似乎是从 rc1 开始修复的错误。
"EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event"是因为页面需要包含hammerjs而引发的
示例:
我已经阅读了关于如何将 hammerjs 与 angular 一起使用的所有其他答案,它们看起来很老套。
默认情况下,HammerJs 已禁用 SwipeDown 和 SwipeUp 方法。以前的所有答案都不正确 angular2 typescript 解决手势问题或覆盖 hammer 的默认设置的方法。
我花了大约 4 个小时来研究 angular2 和 hammerjs 提交。
你在这里:
我们首先需要的是 angular2.
的 hammerjs 类型
typings install github:DefinitelyTyped/DefinitelyTyped/hammerjs/hammerjs.d.ts#de8e80dfe5360fef44d00c41257d5ef37add000a --global --save
接下来我们需要创建自定义覆盖配置 class。
此 class 可用于覆盖所有默认的 hammerjs 和 angular2 hammerjs 配置设置。
hammer.config.ts:
import { HammerGestureConfig } from '@angular/platform-browser';
import {HammerInstance} from "@angular/platform-browser/src/dom/events/hammer_gestures";
export class HammerConfig extends HammerGestureConfig {
buildHammer(element: HTMLElement): HammerInstance {
var mc = new Hammer(element);
mc.get('pinch').set({ enable: true });
mc.get('rotate').set({ enable: true });
mc.add( new Hammer.Swipe({ direction: Hammer.DIRECTION_ALL, threshold: 0 }) );
for (let eventName in this.overrides) {
mc.get(eventName).set(this.overrides[eventName]);
}
return mc;
}
}
我们需要做的最后一件事是打开我们的主要 boostrap 文件并将我们的自定义配置插入到 boostrap 方法中,如下所示:
// ... other imports ...
import { HammerConfig } from './shared/hammer.config';
bootstrap(AppComponent, [
provide(HAMMER_GESTURE_CONFIG, { useClass: HammerConfig })
]);
现在在我们的应用程序中我们可以使用 swipeDown 和 swipeUp
<div class="some-block" (swipeDown)="onSwipeDown"></div>
这个拉取请求启用了默认设置的覆盖,并为我提供了找到正确方法的起点:
好吧,在 OP 之后很久了,但是如果您只有简单的要求并且不想搞砸 hammer.js,这里有一个基本的水平滑动器。只需放入一个组件并添加您自己的 doSwipeLeft
和 doSwipeRight
函数。
touch1 = {x:0,y:0,time:0};
@HostListener('touchstart', ['$event'])
@HostListener('touchend', ['$event'])
//@HostListener('touchmove', ['$event'])
@HostListener('touchcancel', ['$event'])
handleTouch(ev){
var touch = ev.touches[0] || ev.changedTouches[0];
if (ev.type === 'touchstart'){
this.touch1.x = touch.pageX;
this.touch1.y = touch.pageY;
this.touch1.time = ev.timeStamp;
} else if (ev.type === 'touchend'){
var dx = touch.pageX - this.touch1.x;
var dy = touch.pageY - this.touch1.y;
var dt = ev.timeStamp - this.touch1.time;
if (dt < 500){
// swipe lasted less than 500 ms
if (Math.abs(dx) > 60){
// delta x is at least 60 pixels
if (dx > 0){
this.doSwipeLeft(ev);
} else {
this.doSwipeRight(ev);
}
}
}
}
}
我想知道是否可以获得有关移动设备事件的帮助。我正在寻找一种方法来将函数绑定到 Angular 2 中的滑动事件。我在 Github 上的 this issue 中看到提到 Angular 2 使用 Hammer.js 用于移动事件处理。
我在使事件正常运行时遇到了一些问题,因为我收到以下错误:
EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event
我的代码片段如下:
import {Component, View, AfterContentInit} from 'angular2/core';
import {HelperService} from "./helper-service";
import {HammerGesturesPluginCommon} from 'angular2/src/platform/dom/events/hammer_common'
@View({
template: `<div [id]="middleCircle" (swipeleft)="doThis()"></div>`
})
export class ColumnDirective implements AfterContentInit {
constructor(private helperService:HelperService) {}
doThis(){
console.log('This thing has been done.');
}
}
如果我将 Hammer Gestures 添加到我的构造函数中,我会收到此错误:
constructor(private helperService:HelperService, private hammerGesturesPluginCommon: HammerGesturesPluginCommon) {}
EXCEPTION: No provider for t! (ColumnDirective -> t)
任何有关此问题的帮助将不胜感激!
您需要添加
HelperService
和 HammerGesturesPluginCommon
到某处的提供者,在 @Component(...)
注释中或在 bootstrap(AppComponent, [...])
中以消除错误 "No provider for ..."
您是否在入口页面的某处添加了 Hammer.js
的脚本标签?
我能够绕过内置的 Hammer 集成和 运行 我自己的集成:
import { Component, ElementRef, AfterViewInit } from 'angular2/core';
@Component({
selector: 'redeem',
templateUrl: './redeem/components/redeem.html'
})
export class RedeemCmp implements AfterViewInit {
static hammerInitialized = false;
constructor(private el:ElementRef) { }
ngAfterViewInit() {
console.log('in ngAfterViewInit');
if (!RedeemCmp.hammerInitialized) {
console.log('hammer not initialised');
var myElement = document.getElementById('redeemwrap');
var hammertime = new Hammer(myElement);
hammertime.on('swiperight', function(ev) {
console.log('caught swipe right');
console.log(ev);
});
RedeemCmp.hammerInitialized = true;
} else {
console.log('hammer already initialised');
}
}
}
经过大量尝试,我没有成功让 Angular2 的 HammerGesturesPluginCommon 工作(到目前为止)。受 Bill Mayes 回答的启发,我将此作为对他的回答的详细说明提交,我能够开始工作(在 Ipad mini 和 Android phone 上测试)。
基本上,我的解决方案如下。
首先,在你的 index.html 文件的脚本标签中手动引用 hammer.js(我还引用了 hammer-time 来消除 300 毫秒的延迟):
其次,安装 hammerjs 的类型定义(tsd install hammerjs -save)。然后你可以像这样创建一个 Angular2 attibute 指令:
/// <reference path="./../../../typings/hammerjs/hammerjs.d.ts" />
import {Directive, ElementRef, AfterViewInit, Output, EventEmitter} from 'angular2/core';
@Directive({
selector: '[hammer-gestures]'
})
export class HammerGesturesDirective implements AfterViewInit {
@Output() onGesture = new EventEmitter();
static hammerInitialized = false;
constructor(private el: ElementRef) {
}
ngAfterViewInit() {
if (!HammerGesturesDirective.hammerInitialized) {
let hammertime = new Hammer(this.el.nativeElement);
hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
hammertime.on("swipeup", (ev) => {
this.onGesture.emit("swipeup");
});
hammertime.on("swipedown", (ev) => {
this.onGesture.emit("swipedown");
});
hammertime.on("swipeleft", (ev) => {
this.onGesture.emit("swipeleft");
});
hammertime.on("swiperight", (ev) => {
this.onGesture.emit("swiperight");
});
hammertime.on("tap", (ev) => {
this.onGesture.emit("tap");
});
HammerGesturesDirective.hammerInitialized = true;
}
}
}
你需要设置Hammer.DIRECTION_ALL如果你想检测垂直(up/down)滑动(left/right滑动是默认的,不是垂直的).可以在此处找到有关锤子 api 的更多选项:http://hammerjs.github.io/api/#hammer
最后,在你的父组件中你可以做这样的事情:
import {Component} from "angular2/core";
import {HammerGesturesDirective} from "./path/HammerGesturesDirective";
@Component({
selector: "my-ng2-component",
template: `<div style='width:100px; height: 100px;background-color: red'
(onGesture)="doSwipe($event)" hammer-gestures></div>`,
directives: [HammerGesturesDirective]
})
export class MyNg2Component {
constructor() { }
doSwipe(direction: string) {
alert(direction);
}
}
这样,当您想在任何特定元素上启用锤子手势时,您只需要引用属性 hammer-gestures。 注意:该元素似乎需要一个唯一的 ID 才能工作。
我有点犹豫要不要在我的应用程序中添加滑动手势,因为这里的答案似乎暗示它会有点乱。
EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event
只需加载 hammer.js 即可轻松解决此错误。无需自定义代码。
评论中提到的另一个错误似乎是从 rc1 开始修复的错误。
"EXCEPTION: Hammer.js is not loaded, can not bind swipeleft event"是因为页面需要包含hammerjs而引发的
示例:
我已经阅读了关于如何将 hammerjs 与 angular 一起使用的所有其他答案,它们看起来很老套。 默认情况下,HammerJs 已禁用 SwipeDown 和 SwipeUp 方法。以前的所有答案都不正确 angular2 typescript 解决手势问题或覆盖 hammer 的默认设置的方法。 我花了大约 4 个小时来研究 angular2 和 hammerjs 提交。
你在这里:
我们首先需要的是 angular2.
的 hammerjs 类型typings install github:DefinitelyTyped/DefinitelyTyped/hammerjs/hammerjs.d.ts#de8e80dfe5360fef44d00c41257d5ef37add000a --global --save
接下来我们需要创建自定义覆盖配置 class。 此 class 可用于覆盖所有默认的 hammerjs 和 angular2 hammerjs 配置设置。
hammer.config.ts:
import { HammerGestureConfig } from '@angular/platform-browser';
import {HammerInstance} from "@angular/platform-browser/src/dom/events/hammer_gestures";
export class HammerConfig extends HammerGestureConfig {
buildHammer(element: HTMLElement): HammerInstance {
var mc = new Hammer(element);
mc.get('pinch').set({ enable: true });
mc.get('rotate').set({ enable: true });
mc.add( new Hammer.Swipe({ direction: Hammer.DIRECTION_ALL, threshold: 0 }) );
for (let eventName in this.overrides) {
mc.get(eventName).set(this.overrides[eventName]);
}
return mc;
}
}
我们需要做的最后一件事是打开我们的主要 boostrap 文件并将我们的自定义配置插入到 boostrap 方法中,如下所示:
// ... other imports ...
import { HammerConfig } from './shared/hammer.config';
bootstrap(AppComponent, [
provide(HAMMER_GESTURE_CONFIG, { useClass: HammerConfig })
]);
现在在我们的应用程序中我们可以使用 swipeDown 和 swipeUp
<div class="some-block" (swipeDown)="onSwipeDown"></div>
这个拉取请求启用了默认设置的覆盖,并为我提供了找到正确方法的起点:
好吧,在 OP 之后很久了,但是如果您只有简单的要求并且不想搞砸 hammer.js,这里有一个基本的水平滑动器。只需放入一个组件并添加您自己的 doSwipeLeft
和 doSwipeRight
函数。
touch1 = {x:0,y:0,time:0};
@HostListener('touchstart', ['$event'])
@HostListener('touchend', ['$event'])
//@HostListener('touchmove', ['$event'])
@HostListener('touchcancel', ['$event'])
handleTouch(ev){
var touch = ev.touches[0] || ev.changedTouches[0];
if (ev.type === 'touchstart'){
this.touch1.x = touch.pageX;
this.touch1.y = touch.pageY;
this.touch1.time = ev.timeStamp;
} else if (ev.type === 'touchend'){
var dx = touch.pageX - this.touch1.x;
var dy = touch.pageY - this.touch1.y;
var dt = ev.timeStamp - this.touch1.time;
if (dt < 500){
// swipe lasted less than 500 ms
if (Math.abs(dx) > 60){
// delta x is at least 60 pixels
if (dx > 0){
this.doSwipeLeft(ev);
} else {
this.doSwipeRight(ev);
}
}
}
}
}