在Vue KonvaJS中调整和裁剪分组元素

huangapple go评论62阅读模式
英文:

Resizing and clipping grouped element in Vue KonvaJS

问题

我正在尝试在Vue库上使用KonvaJS构建一个应用程序。

我有一个分组图层,在这个分组中绘制了一个圆并放置了图像。

<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-circle>

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

目标是根据圆/分组区域裁剪图像。此外,最终用户可以集体调整组元素的大小。正如你在下面看到的,调整组会影响圆的轮廓。

为了实现这一点,我定义了基本的配置数据集 listGroup_Logo,将其传递到分组图层内,以便在初始渲染时呈现此配置数据。

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

为了添加拖放功能,我在v-stage组件上跟踪@mousedown@touchstart事件,并定义了一个方法handleMousedown来进行进一步的修改。

我试图获取x和y位置以及scaleXscaleY值,并尝试更新圆的配置:

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;

但圆没有更新其值。请参见下面的图像:

在Vue KonvaJS中调整和裁剪分组元素

我已经为我的代码创建了一个沙箱。你可以在这里找到它: https://codesandbox.io/s/bold-fog-ivccnt?file=/src/App.vue

请就如何调整整个组而不干扰线条或圆给予建议。

英文:

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.

&lt;v-group
	v-for=&quot;item in listGroup_Logo&quot;
	:key=&quot;item.name&quot;
	:ref=&quot;item.name&quot;
	:config=&quot;item&quot;
	@dblclick=&quot;check&quot;
	@dragstart=&quot;handleDragStart&quot;
	@dragend=&quot;handleDragEnd&quot;
&gt;

	&lt;v-circle
		v-for=&quot;item in listCircle_Logo&quot;
		:key=&quot;item.name&quot;
		:ref=&quot;item.name&quot;
		:config=&quot;item&quot;
		@dragstart=&quot;handleDragStart&quot;
		@dragend=&quot;handleDragEnd&quot;
	/&gt;

	&lt;v-image
		v-for=&quot;item in listLogo&quot;
		@dragstart=&quot;handleDragStart&quot;
		@dragend=&quot;handleDragEnd&quot;
		:ref=&quot;item.name&quot;
		:key=&quot;item.name&quot;
		:config=&quot;item&quot;
		:keyup.delete=&quot;deleteItemFromKey&quot;
	/&gt;

&lt;/v-group&gt;

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) =&gt; {
        ctx.arc(50, 50, 30, 0, Math.PI * 2, false);
      },
      draggable: true,
      x: 50,
      y: 50,
      name: &quot;Group1676367620342&quot;,
      type: &quot;group&quot;,
    },
],

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 === &quot;undefined&quot;
	? 1
	: e.target.attrs.scaleX;
let scaleY =
  typeof e.target.attrs.scaleY === &quot;undefined&quot;
	? 1
	: e.target.attrs.scaleY;

let obj = {
  clipFunc: (ctx) =&gt; {
	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:

在Vue KonvaJS中调整和裁剪分组元素

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.

答案1

得分: 1

// 每次转换圆形时,您可能需要更改组的裁剪:
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();
  };
},

您可以在此链接中查看示例:codesandbox.io/s/dreamy-hugle-8zqcci?file=/src/App.vue

此外,为了获得更好的视图,我向圆形添加了 strokeScaleEnabled: false,并向变换器添加了 ignoreStroke: true

英文:

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

handleTransform(e) {
      this.listGroup_Logo[0].clipFunc = (ctx) =&gt; {
        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.

huangapple
  • 本文由 发表于 2023年2月16日 19:21:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75471533.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定