RROR TypeError: Cannot read properties of undefined (reading ‘x’) – polygon fabric

I was trying to convert this code which is from the github gist into an angular app and updated the code which as you can see below , the github code gist works fine but when I tried to convert to angular typescript the editpolygon does not seem to work.

The editing of polygon is the main issue with the polygonPositionHandler and anchorWrapper.

Anyone has an idea how and why ? would be much appreciated.

–>> this is the link of the original code which works fine.
https://gist.github.com/restureese/25c75890d20db0b603a692d931e348b4

#ts code

import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
const fabric = require("fabric").fabric;
// import { fabric } from "fabric";

class CustomPolygonControl extends fabric.Control {
  pointIndex: number;

  constructor(options: any, pointIndex: number) {
    super(options);
    this.pointIndex = pointIndex;
  }
}
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements  OnInit, AfterViewInit {
  
  activeLine: any;
  activeShape: any;
  canvas: any;
  lineArray: any[] = [];
  pointArray: any[] = [];
  drawMode = false;
  pointIndex: any;

  constructor() { }

  ngOnInit(): void {
  }

  ngAfterViewInit(): void {
    this.initCanvas();
  }

  initCanvas() {
    this.canvas = new fabric.Canvas('c');
    this.canvas.setHeight(720);
    this.canvas.setWidth(1280);
    const imageUrl = "https://wpmedia.roomsketcher.com/content/uploads/2021/12/14164614/RoomSketcher-House-Floor-Plans-2452430-800.jpg";

    this.canvas.setBackgroundImage(imageUrl, this.canvas.renderAll.bind(this.canvas), {
      backgroundImageOpacity: 0.5,
      backgroundImageStretch: true
    });

    this.canvas.on('mouse:down', (options: any) => this.onMouseDown(options));
    this.canvas.on('mouse:up', () => this.onMouseUp());
    this.canvas.on('mouse:move', (options: any) => this.onMouseMove(options));
    this.canvas.on('object:moving', (option: any) => this.onObjectMove(option));
  }

  onMouseDown(options: any) {
    if (this.drawMode) {
      if (options.target && options.target.id === this.pointArray[0].id) {
        this.generatePolygon(this.pointArray);
      } else {
        this.addPoint(options);
      }
    }

    const evt = options.e;
    if (evt.altKey === true) {
      this.canvas.isDragging = true;
      this.canvas.selection = false;
      this.canvas.lastPosX = evt.clientX;
      this.canvas.lastPosY = evt.clientY;
    }
  }

  onMouseUp() {
    this.canvas.isDragging = false;
    this.canvas.selection = true;
  }

  onMouseMove(options: any) {
    if (this.canvas.isDragging) {
      const e = options.e;
      this.canvas.viewportTransform[4] += e.clientX - this.canvas.lastPosX;
      this.canvas.viewportTransform[5] += e.clientY - this.canvas.lastPosY;
      this.canvas.requestRenderAll();
      this.canvas.lastPosX = e.clientX;
      this.canvas.lastPosY = e.clientY;
    }
    if (this.drawMode) {
      if (this.activeLine && this.activeLine.class === 'line') {
        const pointer = this.canvas.getPointer(options.e);
        this.activeLine.set({
          x2: pointer.x,
          y2: pointer.y
        });
        const points = this.activeShape.get('points');
        points[this.pointArray.length] = {
          x: pointer.x,
          y: pointer.y,
        };
        this.activeShape.set({
          points
        });
      }
      this.canvas.renderAll();
    }
  }

  onObjectMove(option: any) {
    const object = option.target;
    object._calcDimensions();
    object.setCoords();
    this.canvas.renderAll();
  }

  toggleDrawPolygon() {
    if (this.drawMode) {
      this.activeLine = null;
      this.activeShape = null;
      this.lineArray = [];
      this.pointArray = [];
      this.canvas.selection = true;
      this.drawMode = false;
    } else {
      this.canvas.selection = false;
      this.drawMode = true;
    }
  }

  addPoint(options: any) {
    const pointOption = {
      id: new Date().getTime(),
      radius: 5,
      fill: '#ffffff',
      stroke: '#333333',
      strokeWidth: 0.5,
      left: options.e.layerX / this.canvas.getZoom(),
      top: options.e.layerY / this.canvas.getZoom(),
      selectable: false,
      hasBorders: false,
      hasControls: false,
      originX: 'center',
      originY: 'center',
      objectCaching: false,
    };
    const point = new fabric.Circle(pointOption);

    if (this.pointArray.length === 0) {
      point.set({
        fill: 'red'
      });
    }

    const linePoints = [
      options.e.layerX / this.canvas.getZoom(),
      options.e.layerY / this.canvas.getZoom(),
      options.e.layerX / this.canvas.getZoom(),
      options.e.layerY / this.canvas.getZoom(),
    ];
    const lineOption = {
      strokeWidth: 2,
      fill: '#999999',
      stroke: '#999999',
      originX: 'center',
      originY: 'center',
      selectable: false,
      hasBorders: false,
      hasControls: false,
      evented: false,
      objectCaching: false,
    };
    const line = new fabric.Line(linePoints, lineOption);

// Set a custom property 'customClass' on the line object
      (line as any).customClass = 'line';


    if (this.activeShape) {
      const pos = this.canvas.getPointer(options.e);
      const points = this.activeShape.get('points');
      points.push({
        x: pos.x,
        y: pos.y
      });
      const polygon = new fabric.Polygon(points, {
        stroke: '#333333',
        strokeWidth: 1,
        fill: '#cccccc',
        opacity: 0.3,
        selectable: false,
        hasBorders: false,
        hasControls: false,
        evented: false,
        objectCaching: false,
      });
      this.canvas.remove(this.activeShape);
      this.canvas.add(polygon);
      this.activeShape = polygon;
      this.canvas.renderAll();
    } else {
      const polyPoint = [{
        x: options.e.layerX / this.canvas.getZoom(),
        y: options.e.layerY / this.canvas.getZoom(),
      }];
      const polygon = new fabric.Polygon(polyPoint, {
        stroke: '#333333',
        strokeWidth: 1,
        fill: '#cccccc',
        opacity: 0.3,
        selectable: false,
        hasBorders: false,
        hasControls: false,
        evented: false,
        objectCaching: false,
      });
      this.activeShape = polygon;
      this.canvas.add(polygon);
    }

    this.activeLine = line;
    this.pointArray.push(point);
    this.lineArray.push(line);

    this.canvas.add(line);
    this.canvas.add(point);
  }

  generatePolygon(pointArray: any) {
    const points = [];
    for (const point of pointArray) {
      points.push({
        x: point.left,
        y: point.top,
      });
      this.canvas.remove(point);
    }
  
    for (const line of this.lineArray) {
      this.canvas.remove(line);
    }
  
    this.canvas.remove(this.activeShape).remove(this.activeLine);
  
    const polygon = new fabric.Polygon(points, {
      stroke: '#0084ff',
      fill: 'black',
    });
    this.canvas.add(polygon);
  
    this.toggleDrawPolygon();
    this.editPolygon();
  }


  polygonPositionHandler(dim : any, finalMatrix : any, fabricObject : any) {
    var x = (fabricObject.points[this.pointIndex].x - fabricObject.pathOffset.x),
          y = (fabricObject.points[this.pointIndex].y - fabricObject.pathOffset.y);
      return fabric.util.transformPoint(
          { x: x, y: y },
    fabric.util.multiplyTransformMatrices(
      fabricObject.canvas.viewportTransform,
      fabricObject.calcTransformMatrix()
    )
      );
  }

  actionHandler(eventData: any, transform: any, x: any, y: any) {
    const polygon = transform.target;
    const currentControl = polygon.controls[polygon.__corner];
    const mouseLocalPosition = polygon.toLocalPoint(new fabric.Point(x, y), 'center', 'center');
    const polygonBaseSize = polygon._getNonTransformedDimensions();
    const size = polygon._getTransformedDimensions(0, 0);
    const finalPointPosition = {
      x: mouseLocalPosition.x * polygonBaseSize.x / size.x + polygon.pathOffset.x,
      y: mouseLocalPosition.y * polygonBaseSize.y / size.y + polygon.pathOffset.y
    };
    polygon.points[currentControl.pointIndex] = finalPointPosition;
    return true;
  }

  anchorWrapper(anchorIndex: any, fn: any) {
    return (eventData: any, transform: any, x: any, y: any) => {
      const fabricObject = transform.target;
      const point = new fabric.Point(
        fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x,
        fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y
      );
      const absolutePoint = fabric.util.transformPoint(point, fabricObject.calcTransformMatrix());
      const actionPerformed = fn(eventData, transform, x, y);
      const newDim = fabricObject._setPositionDimensions({});
      const polygonBaseSize = fabricObject._getNonTransformedDimensions();
      const newX = (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) / polygonBaseSize.x;
      const newY = (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) / polygonBaseSize.y;
      fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5);
      return actionPerformed;
    };
  }

 

  editPolygon() {
    let activeObject =  this.canvas.getActiveObject();
    if (!activeObject) {
        activeObject =  this.canvas.getObjects()[0];
        this.canvas.setActiveObject(activeObject);
    }

    activeObject.edit = true;
    activeObject.objectCaching = false;

    const lastControl = activeObject.points.length - 1;
    activeObject.cornerStyle = 'circle';
    activeObject.controls = activeObject.points.reduce((acc:any,index:any) => {
        acc['p' + index] = new fabric.Control({
            positionHandler: this.polygonPositionHandler,
            actionHandler: this.anchorWrapper(index > 0 ? index - 1 : lastControl, this.actionHandler),
            actionName: 'modifyPolygon',
            pointIndex: index,
        });
        return acc;
    }, {});

    activeObject.hasBorders = false;
    this.canvas.requestRenderAll();
}

  resizePolygon() {
    let activeObject = this.canvas.getActiveObject();
    if (!activeObject) {
      activeObject = this.canvas.getObjects()[0];
      this.canvas.setActiveObject(activeObject);
    }

    activeObject.edit = false;
    activeObject.objectCaching = false;
    activeObject.controls = fabric.Object.prototype.controls;
    activeObject.cornerStyle = 'rect';
    activeObject.hasBorders = true;

    this.canvas.requestRenderAll();
  }

  clearPolygon() {
    this.canvas.remove(...this.canvas.getObjects());
  }
}

#html code

<div>
  <button type="button" (click)="toggleDrawPolygon()">Draw Polygon</button>
  <button type="button" (click)="editPolygon()">Edit Polygon</button>
  <button type="button" (click)="resizePolygon()">Resize/Move Polygon</button>
  <button type="button" (click)="clearPolygon()">Clear</button>
</div>

<canvas id="c"></canvas>