#javascript #vue.js #konvajs #konva #vue-konva
Вопрос:
Я пытаюсь изменить размер текстового элемента, но когда я пытаюсь увеличить его, я всегда меняю масштаб.
Я настроил параметр transformer, как в документации konvajs vue, и он работает хорошо, затем я настроил его, как в примере js, но при изменении размера текстового элемента текст всегда меняет масштаб, и размер элемента иногда изменяется не на выбранный вами размер, а на гораздо больший размер.
Я основывался на примере в js (https://konvajs.org/docs/select_and_transform/Resize_Text.html#page-title ) и попытался передать его vue.
Я импортировал библиотеку на main.js
import VueKonva from "vue-konva";
Vue.use(VueKonva);
app.js шаблон
<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" :ref="item.name" :config="item" @transformend="handleTransformEnd" />
</template>
<v-transformer ref="transformer" :config="{ enabledAnchors: ['middle-left', 'middle-right'], boundBoxFunc: (oldBox, newBox) => {
if (newBox.width < this.MIN_WIDTH) {
return oldBox;
}
return newBox;
},
}"
/>
</v-layer>
</v-stage>
app.js сценарий
<script>
export default {
name: "App",
data() {
return {
MIN_WIDTH: 20,
config: {
width: window.innerWidth,
height: window.innerHeight,
},
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);
item.width = Math.max(
e.target.width() * e.target.scaleX(),
this.MIN_WIDTH
);
item.scaleX = 1;
item.scaleY = 1;
},
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([]);
}
},
},
};
</script>
Пример с этим кодом
https://codesandbox.io/s/transform-07mwo
Редактировать: обновлено с помощью кода
Комментарии:
1. При запросе в SO, пожалуйста, опубликуйте свой проблемный код, а не все приложение целиком. Это вики, а не форум, и мы хотим, чтобы будущие посетители получили пользу от вашего вопроса. Codesanbox может выйти из строя, или вы можете изменить его, сделав его бесполезным.
2. Спасибо, Obed, я также обновил ответ с помощью приведенного здесь кода
Ответ №1:
Я заставляю его работать с этими изменениями
В теге v-text нам нужно изменить событие transformend на событие transform, чтобы визуально обновить текст без изменения масштаба.
Старый тег v-text
<v-text
:key="item.id"
:ref="item.name"
:config="item"
@transformend="handleTransformEnd"
/>
Обновлен тег v-text
<v-text
:key="item.id"
:ref="item.name"
:config="item"
@transform="handleTransformEnd"
/>
В функции handleTransformEnd мы должны обновить ширину элемента в списке, и в то же время мы должны обновить выбранную форму и обновить масштабирование по X и Y, чтобы оно всегда было равно 1, чтобы оно не масштабировалось.
Старый handleTransformEnd
handleTransformEnd(e) {
const item = this.list.find((i) => i.name === this.selectedShapeName);
item.width = Math.max(
e.target.width() * e.target.scaleX(),
this.MIN_WIDTH
);
item.scaleX = 1;
item.scaleY = 1;
},
Обновленный handleTransformEnd
handleTransformEnd() {
const selectedNode = this.$refs.transformer
.getStage()
.getStage()
.findOne("." this.selectedShapeName);
const item = this.list.find(
(item) => item.name === this.selectedShapeName
);
item.width = item.width * selectedNode.getScaleX();
selectedNode.setScaleX(1);
selectedNode.setScaleY(1);
},