0

I am writing a canvas which draws an image in the component of angular2.

Here is the canvas.component.ts

export class BoardComponent implements  OnInit,  AfterViewInit, AfterViewChecked {

  @ViewChild("visualization") visualization: ElementRef;
  @ViewChild('img') img: ElementRef;

  private context: CanvasRenderingContext2D;
  private element: HTMLImageElement;

  src: string;
  width: number
  height: number

  constructor() {
    this.src = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
  }

  ngOnInit() {
    this.width = 400;
    this.height = 400;
  }

  ngAfterViewInit() {
    this.context = this.visualization.nativeElement.getContext("2d");
    this.element = this.img.nativeElement;
  }

  ngAfterViewChecked() {
    this.context.clearRect(0, 0, this.width, this.height);
    console.log('drawImage');
    // this prints an image element with src I gave
    console.log(this.element);
    this.context.drawImage(this.element, 0, 0, this.width, this.height);
  }
}

and here is the template

<img #img src="{{src}}" style='display: none;' />
<canvas #visualization width="{{width}}" height="{{height}}"></canvas>`

it looks like the image has been loaded, but my canvas is still empty.

I have found many similar questions, but none of them use angular2.

for example, the answer from this one drawImage() not working is that you should wait until the image is loaded.

But I don't know how to check this situation in angular way.

Any suggestion?

thanks.

Edit

I found that maybe the reason is that the image is not loaded when I render it to the canvas.

I add the following code and resize my page, and the canvas does show up.

@HostListener('window:resize')
resize() {
    this.render();
  }
render() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.drawImage(this.element, 0, 0, this.width, this.height);
 }

If this is the reason, the question changes, what is the proper way to add a event listener (like img.onLoad) to the html element in angular2?

alec.tu
  • 1,647
  • 2
  • 20
  • 41

1 Answers1

1

Here I adapted your code to work.

HTML

  <img #img src="{{src}}" (load)="afterLoading()" style='display: none;' /> 
  <canvas #visualization width={{imgWidth}} height={{imgHeight}} "></canvas>

Typescript

export class BoardComponent implements  implements AfterViewInit {

  @ViewChild("visualization") visualization: ElementRef;
  @ViewChild('img') img: ElementRef;

  private context: CanvasRenderingContext2D;
  private element: HTMLImageElement;

  src: string;
  imgWidth: number;
  imgHeight: number;

  constructor() {
    this.imgWidth = 400;
    this.imgHeight = 400;
    this.src = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
  }

  ngAfterViewInit() {
    this.context = this.visualization.nativeElement.getContext("2d");
    this.element = this.img.nativeElement;
  }


  afterLoading(){
    this.context.clearRect(0, 0, this.imgWidth, this.imgHeight);
    console.log('drawImage');
    // this prints an image element with src I gave
    console.log(this.element);
    this.context.drawImage(this.element, 0, 0, this.imgWidth, this.imgHeight);
  }
}

And here is the working DEMO

Vega
  • 27,856
  • 27
  • 95
  • 103
  • OP is drawing the img element on the canvas, no need to display the image element for this. – Kaiido Jul 16 '17 at 10:07
  • Well your answer absolutely doesn't answer the question and thus "*is not helpful*" ,which is a reason to downvote yes. – Kaiido Jul 16 '17 at 10:10
  • The HTMLImageElement doesn't need to be displayed in order to draw it on the HTMLCanvasELement. The question is quite clear : how to wait for the image has loaded in angular, so that it can be used by CanvasRenderingContext2D#drawImage method. this method doesn't care about CSS. You can even draw an HTMLImageElement that is not appended to the document. Your answer doesn't answer the question and I feel you don't understand what is an [HTMLCanvasElement](https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement), or "*canvas*" as named in question. – Kaiido Jul 16 '17 at 10:16
  • A *copy pasta* from the link I mentioned in the comments on the question ? Glad I was able to dig something in a lib I don't know anything about. – Kaiido Jul 16 '17 at 13:46
  • You meant copypasta? – Vega Jul 16 '17 at 13:51
  • Yes that's what I meant. And an example of what I meant in the first comment you replied *"it doesn't work like that in angular!*" from your own plunkr : https://plnkr.co/edit/WUnhFgh10C3205Wm5Kx8?p=preview So yes, it actually works like that in this library too. Glad we both learned today. – Kaiido Jul 16 '17 at 14:20
  • No beware ! There is still a problem with the loading. You are just lucky enough that either the image is currently cached, or that the lib takes longer to execute than the image to load, but if the image has not loaded yet when `ngAfterViewChecked` fires, then the problem will still occur. – Kaiido Jul 16 '17 at 14:27