Angular2:鼠标事件处理(相对于当前位置的移动) [英] Angular2: mouse event handling (movement relative to current position)

查看:1532
本文介绍了Angular2:鼠标事件处理(相对于当前位置的移动)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的用户应该能够通过鼠标在画布中移动(或旋转)对象.发生鼠标事件时,屏幕坐标用于计算到最后一个事件的增量(方向和长度).没什么特别的...

My user should be able to move (or rotate) an object by mouse in a canvas. When mouse events occur the screen coordinates are used to calculate the delta (direction and length) to the last event. Nothing special...

  1. 鼠标移下(获取第一个坐标)
  2. mousemove(获取第n个坐标,计算deltaXY,通过deltaXY移动对象)
  3. mouseup(与第2步相同,并停止mousemove和mouseup事件处理)

在这一系列事件之后,应该可以重复执行相同的操作.

After this chain of events it should be possible to repeat the same action.

在删除toRx调用之后,此过时的示例按预期工作.但是,此处确定了第一个坐标的增量: github.com:rx-draggable

This outdated example works as expected, after removing the toRx calls. But here the delta to the first coordinate is determined: github.com:rx-draggable

这是我努力修改示例中的代码的方法:

Here is my effort to adapt the code from the example:

@Component({
  selector: 'home',
  providers: [Scene],
  template: '<canvas #canvas id="3dview"></canvas>'
})
export class Home {
  @ViewChild('canvas') canvas: ElementRef;
  private scene: Scene;
  private mousedrag = new EventEmitter();
  private mouseup   = new EventEmitter<MouseEvent>();
  private mousedown = new EventEmitter<MouseEvent>();
  private mousemove = new EventEmitter<MouseEvent>();
  private last: MouseEvent;
  private el: HTMLElement;

  @HostListener('mouseup', ['$event'])
  onMouseup(event: MouseEvent) { this.mouseup.emit(event); }

  @HostListener('mousemove', ['$event'])
  onMousemove(event: MouseEvent) { this.mousemove.emit(event); }

  constructor(@Inject(ElementRef) elementRef: ElementRef, scene: Scene) {
    this.el = elementRef.nativeElement;
    this.scene = scene;
  }

  @HostListener('mousedown', ['$event'])
  mouseHandling(event) {
    event.preventDefault();
    console.log('mousedown', event);
    this.last = event;
    this.mousemove.subscribe({next: evt => {
      console.log('mousemove.subscribe', evt);
      this.mousedrag.emit(evt);
    }});
    this.mouseup.subscribe({next: evt => {
      console.log('mousemove.subscribe', evt);
      this.mousedrag.emit(evt);
      this.mousemove.unsubscribe();
      this.mouseup.unsubscribe();
    }});
  }

  ngOnInit() {
    console.log('init');
    this.mousedrag.subscribe({
      next: evt => {
        console.log('mousedrag.subscribe', evt);
        this.scene.rotate(
            evt.clientX - this.last.clientX, 
            evt.clientY - this.last.clientY);
        this.last = evt;
      }
    });
  }
  ...
}

它仅工作一个周期.在mouseup事件之后,我收到此错误:

It works only for one cycle. After the mouseup event i got this error:

未捕获的异常:"mousemove"评估期间发生错误

Uncaught EXCEPTION: Error during evaluation of "mousemove"

原始异常:ObjectUnsubscribedError

ORIGINAL EXCEPTION: ObjectUnsubscribedError

错误上下文:EventEvaluationErrorContext

ERROR CONTEXT: EventEvaluationErrorContext

取消mousemove订阅无效.对于以下所有鼠标移动均重复此错误.

The cancellation of the mousemove subscription does not work. The error is repeating for all following mousemoves.

您知道我的代码有什么问题吗?是否有其他优雅的方法可以解决此问题?

Do you have an idea what is wrong with my code? Is there a different elegant approach to solve this problem?

推荐答案

我相信您的问题出在EventEmitter上的unsubscribe()remove(sub : Subscription)之间.但是也可以不使用订阅(@HostListener创建的订阅除外)来进行操作,并使其易于阅读.我已经稍微重写了您的代码.您可能会考虑将mouseup event放置在documentwindow上,否则,如果将鼠标释放到画布之外,则会出现奇怪的行为.

I believe your problem lies in the difference between unsubscribe() and remove(sub : Subscription) on an EventEmitter. But it is possible to do it without the use of subscriptions (except the ones created by a @HostListener) and make it easy to read. I've rewritten your code a little. You might consider though placing your mouseup event on the document or window, otherwise you get weird behaviour if you release your mouse outside the canvas.

警告:未经测试的代码

@Component({
    selector: 'home',
    providers: [Scene],
    template: '<canvas #canvas id="3dview"></canvas>'
})
export class Home {
    @ViewChild('canvas') 
    canvas: ElementRef;

    private scene: Scene;
    private last: MouseEvent;
    private el: HTMLElement;

    private mouseDown : boolean = false;

    @HostListener('mouseup')
    onMouseup() {
        this.mouseDown = false;
    }

    @HostListener('mousemove', ['$event'])
    onMousemove(event: MouseEvent) {
        if(this.mouseDown) {
           this.scene.rotate(
              event.clientX - this.last.clientX,
              event.clientY - this.last.clientY
           );
           this.last = event;
        }
    }

    @HostListener('mousedown', ['$event'])
    onMousedown(event) {
        this.mouseDown = true;
        this.last = event;
    }

    constructor(elementRef: ElementRef, scene: Scene) {
        this.el = elementRef.nativeElement;
        this.scene = scene;
    }
}

这篇关于Angular2:鼠标事件处理(相对于当前位置的移动)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆