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
相关产品推荐
相关产品推荐

