Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Performance Optimization Request]: Avoid blindly using setCoords; use calcOCoords appropriately when necessary. #10372

Open
4 tasks done
zhe-he opened this issue Dec 31, 2024 · 4 comments

Comments

@zhe-he
Copy link
Contributor

zhe-he commented Dec 31, 2024

CheckList

  • I agree to follow this project's Code of Conduct
  • I have read and followed the Contributing Guide
  • I have searched and referenced existing issues, feature requests and discussions
  • I am filing a FEATURE request.

Description

When I zoom or pan the canvas, I notice that the smoothness differs between selecting a single object, no objects, or all objects. This is quite strange, so I investigated the issue.

setViewportTransform(vpt: TMat2D) {
    super.setViewportTransform(vpt);
    const activeObject = this._activeObject;
    if (activeObject) {
-     // activeObject.setCoords();
+    activeObject.oCoords = activeObject.calcOCoords(); // as well
    }
  }

When selecting or deselecting an element, would it be better to update only oCoords?

_setActiveObject(object: FabricObject, e?: TPointerEvent) {
    ...
    if (isActiveSelection(object) && prevActiveObject !== object) {
      object.set('canvas', this);
    }
-   // object.setCoords();
+  if (isActiveSelection(object)) {
+        InteractiveFabricObject.prototype.setCoords.call(object);
+   } else {
+       object.oCoords = object.calcOCoords();
+   }
    return true;
  }

When adding elements to the canvas, would it be better to update only oCoords?

_onObjectAdded(obj: FabricObject) {
    if (obj.canvas && (obj.canvas as StaticCanvas) !== this) {
      log(
        'warn',
        'Canvas is trying to add an object that belongs to a different canvas.\n' +
          'Resulting to default behavior: removing object from previous canvas and adding to new canvas',
      );
      obj.canvas.remove(obj);
    }
    obj._set('canvas', this);
-  // obj.setCoords();
+  obj.oCoords = obj.calcOCoords();   // as well
    this.fire('object:added', { target: obj });
    obj.fire('added', { target: this });
  }

When the position of an element changes, it calls setCoords to update the cache. Would it be better to use InteractiveFabricObject.prototype.setCoords.call(target) instead?

_enterGroup(object: FabricObject, removeParentTransform?: boolean) {
    ...
-    // this._shouldSetNestedCoords() && object.setCoords();
+   this._shouldSetNestedCoords() && InteractiveFabricObject.prototype.setCoords.call(object);  // as well
    ...
}

_exitGroup(object: FabricObject, removeParentTransform?: boolean) {
    object._set('group', undefined);
    if (!removeParentTransform) {
      applyTransformToObject(
        object,
        multiplyTransformMatrices(
          this.calcTransformMatrix(),
          object.calcTransformMatrix(),
        ),
      );
-     // object.setCoords();
+    InteractiveFabricObject.prototype.setCoords.call(object); // as well

    ...
}

When a shape changes, can it be made more precise?

_finalizeCurrentTransform(e?: TPointerEvent) {
...
-     target.setCoords();
+     if (transform.actionPerformed) {
+        if (transform.action == "drag") {
+                  InteractiveFabricObject.prototype.setCoords.call(target);            
+           } else {
+                target.setCoords();
+           }
+       } else {
+         target.oCoords = target.calcOCoords();
+      }
...
}

Current State

Because I have customized a layout manager (automatic layout), every time setCoords is called, it updates its own position and the positions of its child elements (based on calculated positions). As a result, the setCoords method in my custom group involves a significant amount of computation, which I hope to minimize as much as possible.

Additional Context

No response

@tetap
Copy link

tetap commented Jan 2, 2025

IntersectsWithRect and IntersectsWithObject and _pointIsInObjectSelectionArea both use aCoords. Is this a problem?

@zhe-he
Copy link
Contributor Author

zhe-he commented Jan 3, 2025

#10373

@zhe-he
Copy link
Contributor Author

zhe-he commented Jan 3, 2025

@tetap
They use getCoords to obtain the absolute position. Although it utilizes its own aCoords cache, it will still perform an additional calculation if it's within a group.
What you're asking is not the same question as what I'm addressing in this article.

@zhe-he
Copy link
Contributor Author

zhe-he commented Jan 3, 2025

This is an article that requires discussion. I'm not sure how to adapt it, as it involves too many changes that need to be confirmed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants