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

React项目中如何为Fabric文本元素添加删除图标并实现删除功能?

在React中给Fabric.js文本添加删除按钮并处理事件

好的,我来帮你解决这个问题!要实现文本左上角的删除图标,我们可以把文本和删除按钮组合成一个Fabric Group,这样它们会一起移动和变换,同时给删除按钮绑定点击事件来移除整个组。另外,Fabric.js有自己的事件系统,我们应该用它来处理画布和对象的交互,而不是直接用React的DOM事件。

步骤1:创建删除按钮组件

我们可以用圆形加叉号文字做一个简洁的删除按钮,也可以替换成图片图标。这里用矢量元素实现:

const createDeleteIcon = (textObj) => {
  // 红色圆形背景
  const circle = new fabric.Circle({
    radius: 12,
    fill: '#ff4444',
    left: textObj.left - 15, // 定位到文本左上角外侧
    top: textObj.top - 15,
    selectable: true,
    hoverCursor: 'pointer' // 鼠标悬停显示指针样式
  });
  // 白色叉号文字
  const cross = new fabric.Text('×', {
    fontSize: 16,
    fill: 'white',
    left: textObj.left - 12,
    top: textObj.top - 18,
    selectable: false, // 禁止单独选中文字
    evented: false // 让事件冒泡到父级圆形
  });
  // 把圆形和文字组合成删除按钮
  return new fabric.Group([circle, cross], {
    myid: textObj.myid,
    objecttype: 'delete-icon'
  });
};

步骤2:修改addText方法,组合文本和删除按钮

添加文本时,将文本和删除按钮合并为一个Group,这样它们会作为一个整体被操作:

addText() {
  let newID = new Date().getTime().toString().substr(5);
  let text = new fabric.IText('текст', {
    fontFamily: 'arial black',
    left: 100,
    top: 100,
    myid: newID,
    objecttype: 'text'
  });
  // 创建对应文本的删除图标
  const deleteIcon = createDeleteIcon(text);
  // 组合文本与图标
  const textGroup = new fabric.Group([text, deleteIcon], {
    myid: newID,
    objecttype: 'text-group'
  });
  this.__canvas.add(textGroup);
}

步骤3:绑定Fabric画布点击事件处理删除操作

在componentDidMount中给画布添加鼠标点击监听,判断点击目标是否为删除按钮,若是则移除对应的文本组:

componentDidMount() {
  // 初始化画布(你的原有代码)
  this.__canvas = new fabric.Canvas('meCanvas', {
    preserveObjectStacking: true,
    height: 812,
    width: 375,
    backgroundColor: 'gray'
  });
  let rect = new fabric.Rect({
    left: 100,
    top: 150,
    fill: 'red',
    width: 200,
    height: 200
  });
  this.__canvas.add(rect);

  // 绑定画布点击事件
  this.__canvas.on('mouse:down', (event) => {
    const target = event.target;
    // 判断点击的是删除图标
    if (target?.objecttype === 'delete-icon') {
      // 根据id找到对应的文本组并删除
      const textGroup = this.__canvas.getObjects().find(obj => obj.myid === target.myid);
      if (textGroup) {
        this.__canvas.remove(textGroup);
        this.__canvas.renderAll(); // 重新渲染画布
      }
    }
  });
}

步骤4:修复React Canvas事件问题

你原来代码里的<canvas onClick={console.log('onClick')}会在组件渲染时直接执行,而非点击触发。而且Fabric.js会接管画布的事件处理,所以直接移除这个React事件即可,改用Fabric自身的事件系统。

完整代码

import React from 'react';
import { fabric } from 'fabric';

const createDeleteIcon = (textObj) => {
  const circle = new fabric.Circle({
    radius: 12,
    fill: '#ff4444',
    left: textObj.left - 15,
    top: textObj.top - 15,
    selectable: true,
    hoverCursor: 'pointer'
  });
  const cross = new fabric.Text('×', {
    fontSize: 16,
    fill: 'white',
    left: textObj.left - 12,
    top: textObj.top - 18,
    selectable: false,
    evented: false
  });
  return new fabric.Group([circle, cross], {
    myid: textObj.myid,
    objecttype: 'delete-icon'
  });
};

class Designer extends React.Component {
  componentDidUpdate() {
    console.log('componentDidUpdate ');
  }

  componentDidMount() {
    this.__canvas = new fabric.Canvas('meCanvas', {
      preserveObjectStacking: true,
      height: 812,
      width: 375,
      backgroundColor: 'gray'
    });
    let rect = new fabric.Rect({
      left: 100,
      top: 150,
      fill: 'red',
      width: 200,
      height: 200
    });
    this.__canvas.add(rect);

    // 绑定画布点击事件
    this.__canvas.on('mouse:down', (event) => {
      const target = event.target;
      if (target?.objecttype === 'delete-icon') {
        const textGroup = this.__canvas.getObjects().find(obj => obj.myid === target.myid);
        if (textGroup) {
          this.__canvas.remove(textGroup);
          this.__canvas.renderAll();
        }
      }
    });
  }

  addText() {
    let newID = new Date().getTime().toString().substr(5);
    let text = new fabric.IText('текст', {
      fontFamily: 'arial black',
      left: 100,
      top: 100,
      myid: newID,
      objecttype: 'text'
    });
    const deleteIcon = createDeleteIcon(text);
    const textGroup = new fabric.Group([text, deleteIcon], {
      myid: newID,
      objecttype: 'text-group'
    });
    this.__canvas.add(textGroup);
  }

  render() {
    console.log('render');
    return (
      <div>
        <button id="texts" onClick={() => this.addText()}> TEXT PLEASE </button>
        <canvas id="meCanvas" ref="myFabric" />
      </div>
    );
  }
}

export default Designer;

额外说明

  • 使用Group组合元素,保证文本和删除按钮的位置关系始终同步,移动文本时按钮也会跟随。
  • Fabric.js的事件系统基于画布对象,通过canvas.on监听事件比React DOM事件更适配Fabric的对象模型。
  • 自定义属性myid和objecttype用于快速识别和定位目标元素,避免混淆不同类型的画布对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:44:43