You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue-Konva调整Text元素大小时scale异常变大问题如何解决?

问题原因

缩放异常、尺寸不匹配问题来自两个核心原因:

  • 模板内直接定义boundBoxFunc时this指向异常,最小宽度限制不生效
  • transformend事件中仅修改了Vue响应式数据,没有同步更新Konva原生节点状态,导致Vue异步更新和Konva内部状态不同步

修复步骤

1. 修改模板中的Transformer配置

将原本写在模板内的配置移出到data中,避免this指向错误:

<v-stage ref="stage" :config="config" @mousedown="handleStageMouseDown" @touchstart="handleStageMouseDown">
  <v-layer ref="layer">
    <template v-for="item in list">
      <v-text :key="item.id" :config="item" @transformend="handleTransformEnd" />
    </template>
    <v-transformer ref="transformer" :config="transformerConfig" />
  </v-layer>
</v-stage>

2. 调整脚本配置

在data中新增Transformer配置,同时修改handleTransformEnd方法手动同步Konva节点状态:

<script>
export default {
  name: "App",
  data() {
    return {
      MIN_WIDTH: 20,
      config: {
        width: window.innerWidth,
        height: window.innerHeight,
      },
      // 新增Transformer配置,保证boundBoxFunc的this指向正确
      transformerConfig: {
        enabledAnchors: ['middle-left', 'middle-right'],
        boundBoxFunc: (oldBox, newBox) => {
          if (newBox.width < this.MIN_WIDTH) {
            return oldBox;
          }
          return newBox;
        }
      },
      selectedShapeName: "",
      list: [
        {
          x: 50,
          y: 60,
          fontSize: 20,
          text: "Hello from the Konva framework. Try to resize me.",
          draggable: true,
          width: 200,
          scaleX: 1,
          name: "textResize1",
          height: "auto",
        },
      ],
    };
  },
  methods: {
    handleTransformEnd(e) {
      const item = this.list.find((i) => i.name === this.selectedShapeName);
      if (!item) return;
      
      const newWidth = Math.max(
        e.target.width() * e.target.scaleX(),
        this.MIN_WIDTH
      );
      // 同步更新Vue响应式数据和Konva原生节点属性
      item.width = newWidth;
      item.scaleX = 1;
      item.scaleY = 1;
      e.target.width(newWidth);
      e.target.scaleX(1);
      e.target.scaleY(1);
      
      // 刷新Transformer状态并重绘图层
      this.updateTransformer();
      this.$refs.layer.getNode().draw();
    },
    handleStageMouseDown(e) {
      // clicked on stage - clear selection
      if (e.target === e.target.getStage()) {
        this.selectedShapeName = "";
        this.updateTransformer();
        return;
      }

      // clicked on transformer - do nothing
      const clickedOnTransformer =
        e.target.getParent().className === "Transformer";
      if (clickedOnTransformer) {
        return;
      }

      // find clicked rect by its name
      const name = e.target.name();
      const item = this.list.find((i) => i.name === name);
      if (item) {
        this.selectedShapeName = name;
      } else {
        this.selectedShapeName = "";
      }
      this.updateTransformer();
    },
    updateTransformer() {
      // here we need to manually attach or detach Transformer node
      const transformerNode = this.$refs.transformer.getNode();
      const stage = transformerNode.getStage();
      const { selectedShapeName } = this;

      const selectedNode = stage.findOne("." + selectedShapeName);
      // do nothing if selected node is already attached
      if (selectedNode === transformerNode.node()) {
        return;
      }

      if (selectedNode) {
        // attach to another node
        transformerNode.nodes([selectedNode]);
      } else {
        // remove transformer
        transformerNode.nodes([]);
      }
      // 新增Transformer重绘逻辑
      transformerNode.getLayer().draw();
    },
  },
};
</script>

修改后拖拽调整文本大小时,会直接修改文本的width属性,不会残留scale值,也不会出现尺寸不匹配的异常。

内容的提问来源于stack exchange,提问作者IvanG11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 21:54:04