0
votes

ok so the reason for this question is that i am trying to deal with multiple konva shapes at a time. in the original project the shapes are being selected by drawing a momentary rectangle around the shapes that you want selected (rectangular selection). I have seen some of the other post about this, but they only seem to deal with the selection itself, i have that working.

Here is a codepen example that illustrates the problem. link
Instructions:

  1. click the select button to have the two shapes put in a group and a transformer applied
  2. Rotate and scale the selected shapes.
  3. click the deselect button to have the shapes moved back onto the layer.

The parts that is interresting is after line 92, where i am exploring different methods of moving the shapes back onto the layer.

children.toArray().forEach(e => {
      // Need to apply transformations correctly before putting back on layer

      //Method 1
      if (method === 1) {
        let newTransforms = e.getAbsoluteTransform();
        let localTransforms = e.getTransform();
        let m = newTransforms.getMatrix();
        let matrices = getMatrix(e);

        console.log("matrix before : ");
        console.log(matrices); 

        e.rotation(selectionGroupRotation);
        e.skew({ x: m[1], y: m[2] });
        e.scale({ x: m[0], y: m[3] });
        e.position({ x: m[4], y: m[5] })

        m = newTransforms.getMatrix();
        matrices = getMatrix(e);

        console.log("matrix after : ");
        // console.log(m); 
        console.log(matrices);
      }

      //Method 2
       if (method === 2) {
        let groupPos = selectionGroup.position();
        let point = { x: groupPos.x, y: groupPos.y };
        let groupScale = selectionGroup.scale();
        let groupRotation = selectionGroup.rotation();
        let configGroupMatrix = selectionGroup.getTransform(); 
        let newpos = configGroupMatrix.point(point);

        e.rotation(selectionGroupRotation + e.rotation());
        e.scaleX(groupScale.x * e.scaleX());
        e.scaleY(groupScale.y * e.scaleY());
        let finalpos = {
          x: groupPos.x + e.x(),
          y: groupPos.y + e.y()
                       }
        e.x(finalpos.x);
        e.y(finalpos.y);

      }

      e.moveTo(layer);
    })

The frustrating part is that the function getAbsoluteTransform() seem to give a transformed matrix, but you can't set the transformation matrix of a shape directly. But the solution might be as simple as setting the shapes matrix to the one returned from getAbsoluteTransform()

1

1 Answers

1
votes

Currently, there are no methods to in Konva core to calculate attributes from the matrix. But you can easily find them online.

https://math.stackexchange.com/questions/13150/extracting-rotation-scale-values-from-2d-transformation-matrix

extract rotation, scale values from 2d transformation matrix

From the answers, I made this function to get attrs:

function decompose(mat) {
  var a = mat[0];
  var b = mat[1];
  var c = mat[2];
  var d = mat[3];
  var e = mat[4];
  var f = mat[5];

  var delta = a * d - b * c;

  let result = {
    x: e,
    y: f,
    rotation: 0,
    scaleX: 0,
    scaleY: 0,
    skewX: 0,
    skewY: 0,
  };

  // Apply the QR-like decomposition.
  if (a != 0 || b != 0) {
    var r = Math.sqrt(a * a + b * b);
    result.rotation = b > 0 ? Math.acos(a / r) : -Math.acos(a / r);
    result.scaleX = r;
    result.scaleY = delta / r;
    result.skewX = Math.atan((a * c + b * d) / (r * r));
    result.scleY = 0;
  } else if (c != 0 || d != 0) {
    var s = Math.sqrt(c * c + d * d);
    result.rotation =
      Math.PI / 2 - (d > 0 ? Math.acos(-c / s) : -Math.acos(c / s));
    result.scaleX = delta / s
    result.scaleY = s;
    result.skewX = 0
    result.skewY = Math.atan((a * c + b * d) / (s * s));
  } else {
    // a = b = c = d = 0
  }

  result.rotation *= 180 / Math.PI;
  return result;
}

Then you can use that function to calculate attributes from the absolute transform.

Demo: https://codepen.io/lavrton/pen/dwGPBz?editors=1010