Fabric.js IText互动问题,移动但无法编辑

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

Fabric.js IText interaction issue, moving but not editing

问题

尝试将可编辑、可调整大小、可旋转等的IText组件添加到画布中。添加后可以移动,但无论如何都无法与之交互。

fabric版本 - 5.3.0

vue.js + TS + Vite

这是我的useCanvas组合:

import { fabric } from 'fabric';
import { ref, Ref } from 'vue';
import { useElementSize } from '@vueuse/core';

const MIN_CANVAS_HEIGHT = 500;

export function useCanvas(
  canvasRef: Ref<HTMLCanvasElement | null>,
  canvasContainerRef: Ref<HTMLElement | null>,
  minHeight = MIN_CANVAS_HEIGHT,
) {
  const canvas = ref<fabric.Canvas | null>(null);

  const { width: containerWidth, height: containerHeight } =
    useElementSize(canvasContainerRef);

  const init = () => {
    canvas.value = new fabric.Canvas(canvasRef.value, {
      width: containerWidth.value,
      height: minHeight,
    });
  };

  const addText = (value: string, isEditable = true) => {
    if (!canvas.value) return;

    const text = new fabric.IText(value, {
      left: 50,
      top: 50,
      fill: '#000000',
      fontFamily: 'Arial',
      fontSize: 24,
      fontWeight: 'normal',
      editable: isEditable,
      centeredRotation: true,
      padding: 10,
    });

    // 移除缩放时不保持宽高比的能力
    text.setControlsVisibility({
      mt: false,
      mb: false,
      ml: false,
      mr: false,
    });

    canvas.value.add(text);
  };

  return {
    canvas,
    init,
    addText,
  };
}

这是使用它的Vue组件:

<template>
  <div ref="editorContainerRef" class="image-editor">
    <canvas ref="editorCanvasRef" class="image-editor__canvas" />
    <button class="button" type="button" @click="handleTextAdd">
      <span>添加文本</span>
    </button>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useCanvas } from './composables';

const DEFAULT_TEXT = 'Your unique signature';
const editorContainerRef = ref<HTMLElement | null>(null);
const editorCanvasRef = ref<HTMLCanvasElement | null>(null);

const canvasInstance = useCanvas(editorCanvasRef, editorContainerRef);

const { init, addText } = canvasInstance;

const handleTextAdd = () => {
  addText(DEFAULT_TEXT);
};

onMounted(() => {
  if (!editorCanvasRef.value) return;

  init();
});
</script>

正如你所见,我已经尝试设置可能影响缩放、旋转和编辑能力的每个属性,但它不起作用。但如果我在画布上添加多个文本,然后选择它们,每个文本都开始按预期工作。所以我发现文本在选择为一组之前是不可交互的,我不知道是什么导致了这种行为。

英文:

Trying to add IText component to the canvas that will be editable, resizable, rotatable etc.

It can be moved after adding, but cant be interacted in other way no matter what i do

fabric version - 5.3.0

vue.js + TS + Vite

here is my useCanvas composable

import { fabric } from &#39;fabric&#39;
import { ref, Ref } from &#39;vue&#39;
import { useElementSize } from &#39;@vueuse/core&#39;
const MIN_CANVAS_HEIGHT = 500
export function useCanvas(
canvasRef: Ref&lt;HTMLCanvasElement | null&gt;,
canvasContainerRef: Ref&lt;HTMLElement | null&gt;,
minHeight = MIN_CANVAS_HEIGHT,
) {
const canvas = ref&lt;fabric.Canvas | null&gt;(null)
const { width: containerWidth, height: containerHeight } =
useElementSize(canvasContainerRef)
const init = () =&gt; {
canvas.value = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})
}
const addText = (value: string, isEditable = true) =&gt; {
if (!canvas.value) return
const text = new fabric.IText(value, {
left: 50,
top: 50,
fill: &#39;#000000&#39;,
fontFamily: &#39;Arial&#39;,
fontSize: 24,
fontWeight: &#39;normal&#39;,
editable: isEditable,
centeredRotation: true,
padding: 10,
})
// removing ability to scale without maintaining aspect ratio
text.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false,
})
canvas.value.add(text)
}
}
return {
canvas,
init,
addText,
}

and here is vue component where it is being used

template

 &lt;template&gt;
&lt;div ref=&quot;editorContainerRef&quot; class=&quot;image-editor&quot;&gt;
&lt;canvas ref=&quot;editorCanvasRef&quot; class=&quot;image-editor__canvas&quot; /&gt;
&lt;button class=&quot;button&quot; type=&quot;button&quot; @click=&quot;handleTextAdd&quot;&gt;
&lt;span&gt;{{ &#39;add text&#39; }}&lt;/span&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;

script

&lt;script setup lang=&quot;ts&quot;&gt;
import { ref, onMounted } from &#39;vue&#39;
import { useCanvas } from &#39;./composables&#39;
const DEFAULT_TEXT = &#39;Your unique signature&#39;
const editorContainerRef = ref&lt;HTMLElement | null&gt;(null)
const editorCanvasRef = ref&lt;HTMLCanvasElement | null&gt;(null)
const canvasInstance = useCanvas(editorCanvasRef, editorContainerRef)
const { init, addText } = canvasInstance
const handleTextAdd = () =&gt; {
addText(DEFAULT_TEXT)
}
onMounted(() =&gt; {
if (!editorCanvasRef.value) return
init()
})
&lt;/script&gt;

As you can see i've already tried to set every property that could possibly affect scaling, rotating and editing ability but it doesn't work

But if i add more than one text to canvas and then select both, each of them begins to work as expected

So what i found is that text isn't interactable until you select it in group and i have no idea what causes that behavior

答案1

得分: 0

以下是您要翻译的内容:

For those who will face the same problem in the future:

The problem arises from Vue reactivity, which uses a lot of proxies under the hood. In this particular case, there are some conflicts with the fabric.js library, causing unexpected behavior.

So the solution is to remove any reactivity from fabric.Canvas and any fabric.Object you are trying to interact with.

Many hours of research have led to this small change.

Doesn't work:

const canvas = ref<fabric.Canvas | null>(null)
canvas.value = new fabric.Canvas(canvasRef.value, {
  width: containerWidth.value,
  height: minHeight,
})

Works as expected:

let canvas = null as fabric.Canvas | null
canvas = new fabric.Canvas(canvasRef.value, {
    width: containerWidth.value,
    height: minHeight,
  })
英文:

For those who will face same problem in the future:

The problems goes from Vue reactivity that uses a lot of proxy under the hood, that in that particular case have some conflicts with fabric.js library and causes unexpected behavior

So solution is: remove any reactivity from fabric.Canvas and any fabric.Object you are trying to interact with.

Many hours of research leads to this small change

doesn't work:

 const canvas = ref&lt;fabric.Canvas | null&gt;(null)
canvas.value = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})

works as expected:

let canvas = null as fabric.Canvas | null
canvas = new fabric.Canvas(canvasRef.value, {
width: containerWidth.value,
height: minHeight,
})

huangapple
  • 本文由 发表于 2023年3月3日 23:07:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75628752.html
匿名

发表评论

匿名网友

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

确定