nikolaus
nikolaus

Reputation: 73

HTMLCanvasElement with BrowserAnimationModule

I am trying to add Angular Material Dialog to my component that contains HTMLCanvas element for drawing. But, Material Dialog uses module BrowserAnimationModule (which is imported in app.module.ts) which for some reasons blocks showing the drawing on canvas until I refresh the page. Nothing shows in console.

whiteboard.component.ts

    export class WhiteboardComponent implements OnInit, OnDestroy {
  

  @ViewChild('whiteboard', {static: true})
  board: ElementRef<HTMLCanvasElement>;
  ctx: CanvasRenderingContext2D;
  active = false;
  htmlCanvas: HTMLElement;
  rectCanvas: ClientRect;
  penSize: number;
  penColor: string;
  subscriptions: Subscription[] = [];

  constructor(private canvasService: CanvasService) {
    this.subscriptions.push(this.canvasService
      .getCanvasEvent()
      .subscribe((data: string) => {
        const img = new Image();
        img.src = data;
        this.ctx.drawImage(img, 0, 0);
      }));
  }
  ngOnDestroy(): void {
    this.subscriptions.forEach(sub => sub.unsubscribe());
  }
  

  sendCanvasData() {
    this.canvasService.sendCanvasData(this.board.nativeElement.toDataURL());
  }

  ngOnInit(): void {
    this.penColor = 'black';
    this.penSize = 5;
    this.rectCanvas = this.htmlCanvas.getBoundingClientRect();
    this.ctx = this.board.nativeElement.getContext('2d');
    // Ovaj deo je zbog resizinga
    this.board.nativeElement.height = this.board.nativeElement.offsetHeight;
    this.board.nativeElement.width = this.board.nativeElement.offsetWidth;
    // ***********************


    this.board.nativeElement.addEventListener('mousedown', (evt) => {
      this.sendCanvasData();
      this.startDrawing(evt);
    });
    this.board.nativeElement.addEventListener('mouseup', (evt) => {
      this.sendCanvasData();
      this.endDrawing();
    });
    this.board.nativeElement.addEventListener('mousemove', (evt) => {
      this.sendCanvasData();
      this.draw(evt);
    });

  }



  startDrawing(e: MouseEvent): void {

    this.active = true;
    this.draw(e);


  }

  endDrawing(): void {

    this.active = false;
    this.ctx.beginPath();
  }

  draw(e: MouseEvent): void {

    if (!this.active) { return; }

    this.ctx.lineWidth = this.penSize;
    this.ctx.strokeStyle = this.penColor;
    this.ctx.lineCap = 'round';
    this.ctx.lineTo(e.clientX - this.rectCanvas.left, e.clientY - this.rectCanvas.top);
    this.ctx.stroke();
    this.ctx.beginPath();
    this.ctx.moveTo(e.clientX - this.rectCanvas.left, e.clientY - this.rectCanvas.top);

  }


  onClearCanvas(): void {
    this.ctx.clearRect(0, 0, this.board.nativeElement.width, this.board.nativeElement.height);
    this.sendCanvasData();
  }

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule} from '@angular/forms';
import { MaterialModule} from './material/material.module';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormComponent } from './form/form.component';
import { WhiteboardComponent } from './whiteboard/whiteboard.component';
import { ChatComponent } from './chat/chat.component';
import { PlaygroundComponent } from './playground/playground.component';
import { GameInfoFormComponent } from './game-info-form/game-info-form.component';
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';


@NgModule({
  declarations: [
    AppComponent,
    FormComponent,
    WhiteboardComponent,
    ChatComponent,
    PlaygroundComponent,
    GameInfoFormComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    // tslint:disable-next-line: deprecation
    HttpClientModule,
    ReactiveFormsModule,
    MaterialModule,
    BrowserAnimationsModule
  ],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [GameInfoFormComponent]
})
export class AppModule { }

Upvotes: 0

Views: 140

Answers (1)

Andrei
Andrei

Reputation: 12196

just move most of your ngOnInit hook to ngAfterViewInit. that is the hook where you can rely on component view being rendered.

ngOnInit(): void {
    this.penColor = 'black';
    this.penSize = 5;
}
ngAfterViewInit(): void {
    this.rectCanvas = this.htmlCanvas.getBoundingClientRect();
    this.ctx = this.board.nativeElement.getContext('2d');
    // Ovaj deo je zbog resizinga
    this.board.nativeElement.height = this.board.nativeElement.offsetHeight;
    this.board.nativeElement.width = this.board.nativeElement.offsetWidth;
    // ***********************


    this.board.nativeElement.addEventListener('mousedown', (evt) => {
      this.sendCanvasData();
      this.startDrawing(evt);
    });
    this.board.nativeElement.addEventListener('mouseup', (evt) => {
      this.sendCanvasData();
      this.endDrawing();
    });
    this.board.nativeElement.addEventListener('mousemove', (evt) => {
      this.sendCanvasData();
      this.draw(evt);
    });

  }

Upvotes: 1

Related Questions