goresev
1/17/2018 - 7:58 AM

frame draw

<div class="test-area" #testArea>
  <button (click)="deleteLastFrame()">Delete last frame</button>
</div>

<div class="sometext">
  This is the kind of animation for which using Canvas and requestAnimationFrame is appropriate: There are a lot
  of objects moving around, which in SVG would mean having a lot of DOM nodes on the page. Furthermore, it is a real
  time simulation, where we don't actually know the positions of these objects beforehand. We couldn't use CSS or Element.animate
  because these objects don't fly along straight paths. The paths change all the time as the dynamics of the system
  affect them. For something like this, requestAnimationFrame is exactly the right tool.

  To set up a requestAnimationFrame loop for an Angular component,
  I usually implement the OnInit and OnDestroy lifecycle hooks, and have them maintain a "running"
  flag that will be true after the component is initialized and false after it's been destroyed. This signals that the component is
  "alive" and mounted on the screen. I then also launch the paint loop from ngOnInit() by calling a private paint() method:

</div>
.test-area {
  width: 100%;
  height: 100%;
  z-index: 1;
  position: absolute;
  cursor: crosshair;
}

.selected-area {
  z-index: 2;
  border: 1px solid red;
  position: absolute;
}

.mark {
  z-index: 2;
  border: 1px solid red;
  border-radius: 50%;
  position: absolute;
  width: 20px;
  height: 20px;
}

.temp-selected-area {
  z-index: 2;
  position: absolute;
  background: gray;
  opacity: 0.1;
}
import {Component, ElementRef, HostListener, Renderer2, ViewChild} from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  @ViewChild('testArea') el: ElementRef;
  newElement: any;
  area = {
    firstPoint : {
      x: null,
      y: null
    },
    lastPoint: {
      x: null,
      y: null
    }
  };

  @HostListener('mouseup', ['$event'])
  onMouseUp(event) {
    this.area.lastPoint.x = event.clientX;
    this.area.lastPoint.y = event.clientY;
    setTimeout(() => this.createSelectArea('selected-area'), 500);
  }

  @HostListener('mousedown', ['$event'])
  sendPosition(event) {
    this.area.firstPoint.x = event.clientX;
    this.area.firstPoint.y = event.clientY;
  }

  constructor(
    private element: ElementRef,
    private renderer: Renderer2
  ) {}

  createElement(elClass: string) {
    this.newElement = this.renderer.createElement('div');
    this.renderer.addClass(this.newElement, elClass);
    this.renderer.appendChild(this.el.nativeElement, this.newElement);
  }

  setSelectPosition(pointX, pointY, width, height) {
    this.renderer.setStyle(this.newElement, 'left', (pointX - Math.abs(width)) + 'px');
    this.renderer.setStyle(this.newElement, 'top', (pointY - Math.abs(height)) + 'px');
  }

  createSelectArea(elClass: string) {
    const width = this.area.firstPoint.x - this.area.lastPoint.x;
    const height = this.area.firstPoint.y - this.area.lastPoint.y;
    this.createElement(elClass);

    this.renderer.setStyle(this.newElement, 'width', Math.abs(width) + 'px');
    this.renderer.setStyle(this.newElement, 'height', Math.abs(height) + 'px');

    if ((width > 0) && (height > 0)) {
      this.setSelectPosition(this.area.lastPoint.x, this.area.lastPoint.y, 0, 0);
    } else if ((width < 0) && (height < 0)) {
      this.setSelectPosition(this.area.firstPoint.x, this.area.firstPoint.y, 0, 0);
    } else if ((width < 0) && (height > 0)) {
      this.setSelectPosition(this.area.lastPoint.x, this.area.lastPoint.y, width, 0);
    } else if ((height < 0) && (width > 0)) {
      this.setSelectPosition(this.area.lastPoint.x, this.area.lastPoint.y, 0, height);
    }

  }

  deleteLastFrame() {
    this.renderer.removeChild(this.el, this.newElement);
  }
}