fabricjs / fabric.js

Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser
http://fabricjs.com
Other
28.9k stars 3.5k forks source link

[Bug]: When activating two or more objects, discardActiveObject or setActiveObject after setting props of active objects cause unexpected movement. #10193

Open huangbuyi opened 1 week ago

huangbuyi commented 1 week ago

CheckList

Version

6.0.2

In What environments are you experiencing the problem?

Chrome

Node Version (if applicable)

None

Link To Reproduction

See code below.

Steps To Reproduce

  1. Acitve two or more objects manually.
  2. Set props of active object.
  3. Run discardActiveObject or setActiveObject.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Fabric Test</title>
  <!-- <script src="https://cdn.jsdelivr.net/npm/fabric@latest/dist/index.min.js"></script> -->
  <script src="https://cdn.jsdelivr.net/npm/fabric@6.4.2/dist/index.min.js"></script>
</head>
<body>
  <canvas id="canvas"></canvas>
  <button id="btn">Reproduce Exception</button>
  <p>When activating two or more objects, discardActiveObject or setActiveObject after setting props of active objects cause unexpected movement. </p>
  <p>Click it before select all objects manually or at least two objects</p>
  <script>
    const canvas = new fabric.Canvas('canvas', {
      width: 800,
      height: 800
    });
    const rects = [[20, 20], [40, 20], [60, 20], [80, 20]].map(item => {
      return new fabric.Rect({
        left: item[0],
        top: item[1],
        fill: 'yellow',
        width: 120,
        height: 200,
        strokeWidth: 1,
        stroke: 'lightgreen',
      })
    });
    canvas.add(...rects);

    const btn = document.getElementById('btn');
    btn.addEventListener('click', () => {
      for (const rect of rects) {
        rect.set({
          left: 0,
          top: 0
        })
      }
      canvas.renderAll();
      canvas.discardActiveObject();
      // canvas.setActiveObject(rects[0]);
    });

  </script>
</body>
</html>

Expected Behavior

All objects move to right position.

image

Actual Behavior

Active objects move to wrong position.

Origin positions:

image

Unexcepted positions:

image

I found this problems in v5.3.0, then I upgraded to latest version, the problem was still existed. Is this a real problem, or just I did something wrong? To fix this, I have to discardActiveObject before set object's props then setActiveObject same objects back in my project.

Error Message & Stack Trace

No response

zhe-he commented 4 days ago

When A and B (multiple elements) are selected, an active group (C) is created internally. Setting the position of A means setting A's position relative to C. The design is such that you need to deselect A before setting its position.