react实现leaferjs编辑器功能点之右键点击菜单

实现功能:编辑器单个元素右键点击需要在鼠标位置出现菜单项

思路:leaferjs有右键点击事件,事件回调函数参数中有x和y坐标,那么在获得容器dom后可以直接使用绝对定位进行偏移

简化点:右键点击菜单不是出现的固定ui,因此使用多余变量进行维护一直是我不怎么喜欢的,并且声明式使用函数还需要传递各种参数,使用Context又难免耦合,因此我使用指令式组件封装针对x和y的一个组件,与leaferjs和要制作的编辑器无关。(指令式封装参考我的另一篇文章)

ts 复制代码
import React, { FC, useRef } from 'react';
import { useClickAway } from 'ahooks';
import { createPortal } from 'react-dom';
import { css } from '@emotion/css';
import { appInstance } from '@/runTime';
import { InstructionMountProps } from '@/hooks/useElementsContextHolder';

interface Props {
  container: HTMLDivElement
  x: number
  y: number
  node: React.ReactNode
}

const CoordinateDom: FC<Props & InstructionMountProps<null>> = (props) => {
  const { container, x, y, node, closeResolve } = props;
  const ref = useRef<HTMLDivElement>(null);

  useClickAway(() => {
    closeResolve();
  }, ref, ['click', 'contextmenu']);

  return (
    createPortal(
      <div ref={ref} className={css`position: absolute;left: ${x}px;top: ${y}px`}>
        {node}
      </div>,
      container,
    )
  );
};

export const openCoordinateDomPromise = (args: Props) => {
  return appInstance.getContextHolder().instructionMountPromise<Props, null>({
    Component: CoordinateDom,
    props: args,
  });
};

使用如下:

ts 复制代码
const rect_1 = Rect.one({
  editable: true,
  fill: '#FEB027',
  cornerRadius: [20, 0, 0, 20],
  zIndex: 2,
}, 100, 100);

rect_1.on(PointerEvent.MENU, (e) => {
  e.stop();
  openCoordinateDomPromise({
    container: this.containerRef.current,
    x: e.x,
    y: e.y,
    node: (
      <div className={css`width: 100px;height: 100px`}>1fefe24</div>
    ),
  });
});

简单封装如上,如菜单位置临界等问题以后在加相关处理逻辑,也可以使用antd的dropdown,但既然是以学习为目的最好是自己实现。

相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁5 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95275 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大5 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师5 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学5 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端