Repository: plait-board/drawnix
File: packages/drawnix/src/utils/laser-pointer.ts (TypeScript)

Code before:
} from 'laser-pen';

export const LASER_POINTER_ID = 'laser-pointer';

const calculateRatio = (context: any): number => {
  const backingStore =
    context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio ||
    1;
  return (window.devicePixelRatio || 1) / backingStore;
};

export class LaserPointer {
  private mouseTrack: IOriginalPointData[] = [];
  private mouseMoveHandler: ((event: MouseEvent) => void) | null = null;
  private resizeHandler: (() => void) | null = null;
  private cvsDom: HTMLCanvasElement | null = null;
  private ctx: CanvasRenderingContext2D | null = null;
  private canvasPos: DOMRect | null = null;
  private drawing = false;

  public init(dom: HTMLCanvasElement): void {
    this.cvsDom = dom;
    this.ctx = this.cvsDom.getContext('2d') as CanvasRenderingContext2D;
    this.canvasPos = this.cvsDom.getBoundingClientRect();
    
    this.mouseMoveHandler = (event: MouseEvent) => {
      if (!this.canvasPos) return;
      const relativeX = event.clientX - this.canvasPos.x;
      const relativeY = event.clientY - this.canvasPos.y;
      this.mouseTrack.push({
        x: relativeX,
        y: relativeY,
        time: Date.now(),
      });
      this.ctx && this.startDraw();
    };
    
    this.resizeHandler = () => this.setCanvasSize();
    document.addEventListener('mousemove', this.mouseMoveHandler);
    window.addEventListener('resize', this.resizeHandler);
    
    this.setCanvasSize();
  }

  public destroy(): void {
    if (this.mouseMoveHandler) {

Review comment (suggestion):
I am curious why we need to set the dom as a parameter but not just using `laserPointer.init(document.querySelector(`#${LASER_POINTER_ID}`) as HTMLCanvasElement);` in `with-freehand-erase.ts`? Since I have no idea when will we have canvas with different `LASER_POINTER_ID` and both implement lazer pointer effect in Drawnix

Code after:
  setRoundCap,
} from 'laser-pen';

export const LASER_POINTER_CLASS_NAME = 'laser-pointer';

const calculateRatio = (context: any): number => {
  const backingStore =
    context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio ||
    1;
  return (window.devicePixelRatio || 1) / backingStore;
};

export class LaserPointer {
  private mouseTrack: IOriginalPointData[] = [];
  private mouseMoveHandler: ((event: MouseEvent) => void) | null = null;
  private resizeHandler: (() => void) | null = null;
  private cvsDom: HTMLCanvasElement | null = null;
  private ctx: CanvasRenderingContext2D | null = null;
  private canvasPos: DOMRect | null = null;
  private drawing = false;
  private container: HTMLElement | null = null;

  public init(board: PlaitBoard): void {
    this.container = PlaitBoard.getBoardContainer(board).closest(
      '.drawnix'
    ) as HTMLElement;
    this.cvsDom = this.container.querySelector(
      `.${LASER_POINTER_CLASS_NAME}`
    ) as HTMLCanvasElement;
    this.ctx = this.cvsDom.getContext('2d') as CanvasRenderingContext2D;
    this.canvasPos = this.cvsDom.getBoundingClientRect();

    this.mouseMoveHandler = (event: MouseEvent) => {
      if (!this.canvasPos) return;
      const relativeX = event.clientX - this.canvasPos.x;
      const relativeY = event.clientY - this.canvasPos.y;
      this.mouseTrack.push({
        x: relativeX,
        y: relativeY,
        time: Date.now(),
      });
      this.ctx && this.startDraw();
    };

    this.resizeHandler = () => this.setCanvasSize();
    this.container.addEventListener('pointermove', this.mouseMoveHandler);