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

FabricJS自定义旋转图标:实现鼠标悬停时切换图标图片

FabricJS自定义旋转图标悬停切换解决方案

直接给图片元素绑定onmouseover事件无效的原因是:FabricJS的旋转图标是通过Canvas API绘制的像素内容,并非真实DOM元素,鼠标事件无法直接绑定到绘制出来的图标上。需要借助FabricJS的画布事件系统,手动检测鼠标是否处于旋转图标区域,再切换图片并重绘。

实现步骤及代码示例

  1. 提前加载两张状态的图标图片
    确保正常状态和悬停状态的图标都加载完成后再进行后续操作,避免绘制时图片未就绪:
// 封装图片加载Promise
function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = reject;
    img.src = src;
  });
}

// 声明全局变量存储两张图标
let rotationIconNormal, rotationIconHover;
// 标记当前是否悬停在旋转图标上
let isRotationIconHovered = false;

// 批量加载图标
Promise.all([
  loadImage("LibraryTrans.png"), // 正常状态图标路径
  loadImage("LibraryHoverTrans.png") // 悬停状态图标路径
]).then(([normal, hover]) => {
  rotationIconNormal = normal;
  rotationIconHover = hover;
  // 加载完成后初始化Canvas并设置自定义旋转图标
  initCanvas();
});
  1. 初始化Canvas并绑定鼠标移动事件
    在鼠标移动时,检测当前选中对象的旋转图标区域是否包含鼠标指针:
function initCanvas() {
  const canvas = new fabric.Canvas('your-canvas-id');
  
  // 绑定鼠标移动事件
  canvas.on('mouse:move', (options) => {
    if (!options.target) {
      // 无选中对象时重置悬停状态
      if (isRotationIconHovered) {
        isRotationIconHovered = false;
        canvas.renderAll();
      }
      return;
    }

    const target = options.target;
    const pointer = canvas.getPointer(options.e);
    const cornerSize = canvas.cornerSize;

    // 计算旋转图标的实际位置(考虑对象旋转后的坐标)
    const rotationPoint = target.getRotatedPoint(
      new fabric.Point(target.left + target.width / 2, target.top),
      target.angle
    );

    // 创建临时矩形模拟旋转图标的点击区域
    const hoverArea = new fabric.Rect({
      left: rotationPoint.x - cornerSize / 2,
      top: rotationPoint.y - cornerSize / 2,
      width: cornerSize,
      height: cornerSize,
      angle: target.angle
    });

    // 更新悬停状态,状态变化时触发重绘
    const wasHovered = isRotationIconHovered;
    isRotationIconHovered = hoverArea.containsPoint(pointer);
    if (wasHovered !== isRotationIconHovered) {
      canvas.renderAll();
    }
  });

  // 设置自定义旋转图标渲染函数
  canvas.controlsUtils.renderRotationIcon = renderRotationIcon;
}
  1. 修改自定义渲染函数,根据状态切换图片
    在绘制旋转图标时,根据isRotationIconHovered状态选择对应的图片:
function renderRotationIcon(ctx, left, top, styleOverride, fabricObject) {
  const size = this.cornerSize;
  ctx.save();
  ctx.translate(left, top);
  ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
  // 根据悬停状态选择要绘制的图标
  const currentIcon = isRotationIconHovered ? rotationIconHover : rotationIconNormal;
  ctx.drawImage(currentIcon, -size / 2, -size / 2, size, size);
  ctx.restore();
}

补充说明

  • 如果你的旋转图标位置不是默认的顶部中间,需要调整rotationPoint的计算逻辑,对应你自定义的旋转角位置。
  • 若使用TypeScript,需要给相关变量添加类型声明,或者保留原代码中的//@ts-ignore注释。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:25:23