Chr*_*ris 18 angular2-directives rxjs5 angular
我一直在尝试使用Angular 2来使用可拖动的div工作.我使用angular2-examples repo中的这个示例作为起点,只是真正调整代码来解释toRx()方法的删除.代码有效,但它不考虑mouseout事件.这意味着如果我单击一个Draggable div,然后慢慢移动鼠标,div将随鼠标移动.但是如果我移动鼠标的速度太快,mouseout则会发送一个mousemove事件而不是一个事件,拖动停止.
在鼠标移动到目前为止mouseout触发事件后,如何保持拖动?我已经尝试将mouseout事件流与mousemove一个事件流合并,以便将mouseout事件视为一个事件mousemove,但这不起作用.
我正在使用Angular 2.0.0-beta.12.
import {Component, Directive, HostListener, EventEmitter, ElementRef, OnInit} from 'angular2/core';
import {map, merge} from 'rxjs/Rx';
@Directive({
selector: '[draggable]'
})
export class Draggable implements OnInit {
mouseup = new EventEmitter();
mousedown = new EventEmitter();
mousemove = new EventEmitter();
mouseout = new EventEmitter();
@HostListener('mouseup', ['$event'])
onMouseup(event) {
this.mouseup.emit(event);
}
@HostListener('mousedown', ['$event'])
onMousedown(event) {
this.mousedown.emit(event);
return false; // Call preventDefault() on the event
}
@HostListener('mousemove', ['$event'])
onMousemove(event) {
this.mousemove.emit(event);
}
@HostListener('mouseout', ['$event'])
onMouseout(event) {
this.mouseout.emit(event);
return false; // Call preventDefault() on the event
}
constructor(public element: ElementRef) {
this.element.nativeElement.style.position = 'relative';
this.element.nativeElement.style.cursor = 'pointer';
map;
merge;
this.mousedrag = this.mousedown.map(event => {
return {
top: event.clientY - this.element.nativeElement.getBoundingClientRect().top
left: event.clientX - this.element.nativeElement.getBoundingClientRect().left,
};
})
.flatMap(
imageOffset => this.mousemove.merge(this.mouseout).map(pos => ({
top: pos.clientY - imageOffset.top,
left: pos.clientX - imageOffset.left
}))
.takeUntil(this.mouseup)
);
}
ngOnInit() {
this.mousedrag.subscribe({
next: pos => {
this.element.nativeElement.style.top = pos.top + 'px';
this.element.nativeElement.style.left = pos.left + 'px';
}
});
}
}
@Component({
selector: 'my-app',
template: `
<div draggable>
<h1>Hello, World!</h1>
</div>
`,
directives: [Draggable,],
})
export class AppComponent {
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*ris 26
我在RxJs中找到了答案如何处理文档事件.问题的关键是当鼠标悬停在该元素上时,鼠标事件仅发送到元素.所以我们确实希望mousedown事件仅限于特定元素,但我们必须跟踪全局 mousemove和mouseup事件.这是新代码.注意@HostListener装饰器的使用,onMouseup并onMousemove指定目标为document:mouseup和document:mousemove.这是全局事件通过管道传输到Rx流的方式.
HostListener的官方angular2文档没有提到这种target:eventName语法,但是这个2.0.0-alpha.24的旧dart文档确实提到了它.它似乎仍然在2.0.0-beta.12中工作.
@Directive({
selector: '[draggable]'
})
export class Draggable implements OnInit {
mouseup = new EventEmitter<MouseEvent>();
mousedown = new EventEmitter<MouseEvent>();
mousemove = new EventEmitter<MouseEvent>();
mousedrag: Observable<{top, left}>;
@HostListener('document:mouseup', ['$event'])
onMouseup(event: MouseEvent) {
this.mouseup.emit(event);
}
@HostListener('mousedown', ['$event'])
onMousedown(event: MouseEvent) {
this.mousedown.emit(event);
return false; // Call preventDefault() on the event
}
@HostListener('document:mousemove', ['$event'])
onMousemove(event: MouseEvent) {
this.mousemove.emit(event);
}
constructor(public element: ElementRef) {
this.element.nativeElement.style.position = 'relative';
this.element.nativeElement.style.cursor = 'pointer';
this.mousedrag = this.mousedown.map(event => {
return {
top: event.clientY - this.element.nativeElement.getBoundingClientRect().top
left: event.clientX - this.element.nativeElement.getBoundingClientRect().left,
};
})
.flatMap(
imageOffset => this.mousemove.map(pos => ({
top: pos.clientY - imageOffset.top,
left: pos.clientX - imageOffset.left
}))
.takeUntil(this.mouseup)
);
}
ngOnInit() {
this.mousedrag.subscribe({
next: pos => {
this.element.nativeElement.style.top = pos.top + 'px';
this.element.nativeElement.style.left = pos.left + 'px';
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
你可以用这个: npm install ng2draggable
使用[ng2-draggable]="true",别忘了="true"
你可以在这里找到它
https://github.com/cedvdb/ng2draggable
这是代码:
@Directive({
selector: '[ng2-draggable]'
})
export class Draggable implements OnInit{
topStart:number=0;
leftStart:number=0;
_allowDrag:boolean = true;
md:boolean;
constructor(public element: ElementRef) {}
ngOnInit(){
// css changes
if(this._allowDrag){
this.element.nativeElement.style.position = 'relative';
this.element.nativeElement.className += ' cursor-draggable';
}
}
@HostListener('mousedown', ['$event'])
onMouseDown(event:MouseEvent) {
if(event.button === 2)
return; // prevents right click drag, remove his if you don't want it
this.md = true;
this.topStart = event.clientY - this.element.nativeElement.style.top.replace('px','');
this.leftStart = event.clientX - this.element.nativeElement.style.left.replace('px','');
}
@HostListener('document:mouseup')
onMouseUp(event:MouseEvent) {
this.md = false;
}
@HostListener('document:mousemove', ['$event'])
onMouseMove(event:MouseEvent) {
if(this.md && this._allowDrag){
this.element.nativeElement.style.top = (event.clientY - this.topStart) + 'px';
this.element.nativeElement.style.left = (event.clientX - this.leftStart) + 'px';
}
}
@HostListener('touchstart', ['$event'])
onTouchStart(event:TouchEvent) {
this.md = true;
this.topStart = event.changedTouches[0].clientY - this.element.nativeElement.style.top.replace('px','');
this.leftStart = event.changedTouches[0].clientX - this.element.nativeElement.style.left.replace('px','');
event.stopPropagation();
}
@HostListener('document:touchend')
onTouchEnd() {
this.md = false;
}
@HostListener('document:touchmove', ['$event'])
onTouchMove(event:TouchEvent) {
if(this.md && this._allowDrag){
this.element.nativeElement.style.top = ( event.changedTouches[0].clientY - this.topStart ) + 'px';
this.element.nativeElement.style.left = ( event.changedTouches[0].clientX - this.leftStart ) + 'px';
}
event.stopPropagation();
}
@Input('ng2-draggable')
set allowDrag(value:boolean){
this._allowDrag = value;
if(this._allowDrag)
this.element.nativeElement.className += ' cursor-draggable';
else
this.element.nativeElement.className = this.element.nativeElement.className
.replace(' cursor-draggable','');
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
33078 次 |
| 最近记录: |