Изменение размера текста в vue конвайсе

#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);
},