하회탈
110
2020-04-09 10:50:35
1
200

Angular 이벤트리스너에서 함수부르기에 관해...


https://stackblitz.com/edit/angular-zkmqyh


멋대로 짠 코딩이라 지적부분이 많을거로 예상됩니다.

고수님들의 조언 부탁드립니다!


캔버스에서 마우스 클릭시에 그림을 그릴수 있도록 코딩중인데

이벤트 리스너(mouseListener)에서 밖에있는 함수를 부를경우 함수로 인지하지 못하고 실행이 불가능 하더군요.

해결방안이 있을까요?

0
  • 답변 1

  • 원푠듯
    290
    2020-04-09 12:20:53 작성 2020-04-09 12:26:28 수정됨


    <div>
      <p>canvas example</p>
      <canvas id="canvas" width="500" height="500" (mousedown)="mouseListener($event)" (mousemove)="mouseListener($event)" (mouseup)="mouseListener($event)"></canvas>
    </div>


    이렇게 해보세요. 그리고 ngOnInit에서 엘리먼트 호출하면 컴포넌트 렌더링 전이라 호출 안 될텐데요.


    만약 반드시 컨트롤러 안에서 리스너를 붙어야겠다면, 다음과 같이 할 수 있습니다.


    
      ngAfterViewInit() {
        this.canvas = document.getElementById('canvas') as HTMLCanvasElement;
       // 이것도 아마 라이프사이클 때문에 제대로 호출 안 될 겁니다. 그럴 경우 비동기 HACK을 써야합니다.
       
       const handler = this.mouseListener.bind(this);
    
        this.canvas.addEventListener("mousedown", handler);
        this.canvas.addEventListener("mousemove", handler);
        this.canvas.addEventListener("mouseup", handler);
      }


    기존에 함수 호출이 안 되었던 이유는 addEventListener에서 this를 바인딩 해버렸기 때문입니다. 람다식(Arrow Function)을 사용하거나 bind로 this를 바인딩해줘야 합니다.


    그리고 Angular에서 DOM을 직접 다뤄야 할 경우에는, ViewChild와 Render를 사용하는 걸 권장합니다. ViewChild와 ViewChildren은 비동기 Hack 없이도 ngAfterViewInit 단계에서 엘리먼트의 호출을 보장합니다(ng-if 등으로 렌더링 안 되어있지 않는 한).


    constructor(private renderer: Renderer2) {}
    
    @ViewChild('#canvas', { static: false }) canvasElRef: ElementRef;
    
    ngAfterViewInit() {
        const canvasEl = this.canvasElRef.nativeElement;
        const handler = this.mouseListener.bind(this);
    
        this.renderer.listen(canvasEl, 'mousedown', handler);
        this.renderer.listen(canvasEl, 'mousemove', handler);
        this.renderer.listen(canvasEl, 'mouseup', handler);
    }


  • 로그인을 하시면 답변을 등록할 수 있습니다.