javascriptkonvajskonvavue-konva

Resizing and clipping grouped element in Vue KonvaJS


I'm trying to build an application on KonvaJS with the Vue library.

I've got a group layer where I'm drawing a circle and placing images inside this group.

<v-group
    v-for="item in listGroup_Logo"
    :key="item.name"
    :ref="item.name"
    :config="item"
    @dblclick="check"
    @dragstart="handleDragStart"
    @dragend="handleDragEnd"
>

    <v-circle
        v-for="item in listCircle_Logo"
        :key="item.name"
        :ref="item.name"
        :config="item"
        @dragstart="handleDragStart"
        @dragend="handleDragEnd"
    />

    <v-image
        v-for="item in listLogo"
        @dragstart="handleDragStart"
        @dragend="handleDragEnd"
        :ref="item.name"
        :key="item.name"
        :config="item"
        :keyup.delete="deleteItemFromKey"
    />

</v-group>

The goal is to clip the images as per the circle/group area. Also, the end user can resize the group element collectively. As you can see below, resizing the group effects the circle strokes.

To achieve this I defined the basic configuration dataset listGroup_Logo to be passed inside the group layer, so this config data renders at the initial rendering.

listGroup_Logo: [
    {
      clipFunc: (ctx) => {
        ctx.arc(50, 50, 30, 0, Math.PI * 2, false);
      },
      draggable: true,
      x: 50,
      y: 50,
      name: "Group1676367620342",
      type: "group",
    },
],

To add drag and drop functionality I'm tracking @mousedown and @touchstart events at v-stage component and defined a method handleMousedown to do the further modifications.

I'm trying to fetch the x and y positions along with the scaleX and scaleY values and trying to update the circle configs:

this.listCircle_Logo[objIndex] = e.target.attrs;

let scaleX =
  typeof e.target.attrs.scaleX === "undefined"
    ? 1
    : e.target.attrs.scaleX;
let scaleY =
  typeof e.target.attrs.scaleY === "undefined"
    ? 1
    : e.target.attrs.scaleY;

let obj = {
  clipFunc: (ctx) => {
    ctx.arc(
      50 * scaleX,
      50 * scaleY,
      30 * scaleX,
      0,
      Math.PI * 2,
      false
    );
  },
};

this.listGroup_Logo[0].clipFunc = obj.clipFunc;

But the circle is not updating its values. See the image below:

KonvaJS group drag issue

I've made a sandbox for my code. You can find it here: https://codesandbox.io/s/bold-fog-ivccnt?file=/src/App.vue

Please advise on how to resize the entire group without disturbing the strokes or circles.


Solution

  • You may need to change the clipping of your group every time you transform circle:

    handleTransform(e) {
          this.listGroup_Logo[0].clipFunc = (ctx) => {
            ctx.save();
            ctx.scale(e.target.scaleX(), e.target.scaleY())
            ctx.arc(
              e.target.x() / e.target.scaleX(),
              e.target.y() / e.target.scaleY(),
              30,
              0,
              Math.PI * 2,
              false
            );
            ctx.restore();
          };
        },
    

    https://codesandbox.io/s/dreamy-hugle-8zqcci?file=/src/App.vue

    Also for a bit better view I added strokeScaleEnabled: false to circle and ignoreStroke: true to transformer.