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

能否在TinyMCE React编辑器中添加选中文本触发的气球工具栏?

在TinyMCE React基础版中实现气球编辑器(选中文本弹出工具栏)

TinyMCE React的基础版(开源核心版)不自带官方的气球编辑器功能——官方的balloontoolbar插件属于TinyMCE Premium付费套件的一部分,基础版无法直接启用该插件。

但如果不想升级到付费版,完全可以通过自定义代码实现类似的"选中文本弹出工具栏"效果,具体方案如下:


自定义实现步骤

  1. 监听编辑器选区变化:通过TinyMCE的selectionchange事件,判断当前是否有选中的文本。
  2. 定位工具栏位置:获取选区的DOM矩形位置,计算自定义工具栏的浮动坐标。
  3. 实现工具栏交互:给自定义工具栏的按钮绑定编辑器命令(如加粗、斜体等),点击时调用编辑器的execCommand方法执行对应操作。
  4. 处理隐藏逻辑:点击编辑器外部或选区取消时,隐藏工具栏。

示例代码

import { useRef, useState, useEffect } from 'react';
import { Editor } from '@tinymce/tinymce-react';

// 自定义气球工具栏组件
const CustomBalloonToolbar = ({ isVisible, position, onCommand }) => {
  if (!isVisible) return null;
  return (
    <div 
      style={{
        position: 'absolute',
        top: `${position.top - 40}px`,
        left: `${position.left}px`,
        background: '#ffffff',
        border: '1px solid #e0e0e0',
        borderRadius: '6px',
        padding: '6px',
        boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
        zIndex: 10000,
        display: 'flex',
        gap: '8px'
      }}
    >
      <button 
        onClick={() => onCommand('bold')}
        style={{ border: 'none', background: 'transparent', cursor: 'pointer', padding: '4px 8px' }}
      >
        <strong>B</strong>
      </button>
      <button 
        onClick={() => onCommand('italic')}
        style={{ border: 'none', background: 'transparent', cursor: 'pointer', padding: '4px 8px' }}
      >
        <em>I</em>
      </button>
      <button 
        onClick={() => onCommand('underline')}
        style={{ border: 'none', background: 'transparent', cursor: 'pointer', padding: '4px 8px' }}
      >
        <u>U</u>
      </button>
    </div>
  );
};

const EditorWithBalloonToolbar = () => {
  const editorRef = useRef(null);
  const [toolbarVisible, setToolbarVisible] = useState(false);
  const [toolbarPosition, setToolbarPosition] = useState({ top: 0, left: 0 });

  // 监听编辑器选区变化
  const handleEditorSetup = (editor) => {
    editor.on('selectionchange', () => {
      const selection = editor.selection.getSel();
      if (!selection.isCollapsed) {
        const rangeRect = selection.getRangeAt(0).getBoundingClientRect();
        // 计算工具栏位置(居中对齐选区)
        setToolbarPosition({
          top: rangeRect.top + window.scrollY,
          left: rangeRect.left + window.scrollX + (rangeRect.width / 2) - 45
        });
        setToolbarVisible(true);
      } else {
        setToolbarVisible(false);
      }
    });
  };

  // 点击编辑器外部隐藏工具栏
  useEffect(() => {
    const handleClickOutside = (e) => {
      const editorContainer = document.querySelector('.tox-editor-container');
      if (editorContainer && !editorContainer.contains(e.target) && toolbarVisible) {
        setToolbarVisible(false);
      }
    };
    document.addEventListener('click', handleClickOutside);
    return () => document.removeEventListener('click', handleClickOutside);
  }, [toolbarVisible]);

  // 执行编辑器命令
  const executeEditorCommand = (command) => {
    editorRef.current?.editor.execCommand(command);
  };

  return (
    <div style={{ position: 'relative', maxWidth: '800px', margin: '20px auto' }}>
      <Editor
        ref={editorRef}
        apiKey="your-api-key" // 替换为你的TinyMCE API Key(基础版免费可用)
        init={{
          height: 500,
          menubar: false,
          toolbar: false, // 隐藏默认工具栏
          plugins: 'advlist autolink lists link image charmap',
          branding: false
        }}
        onSetup={handleEditorSetup}
      />
      <CustomBalloonToolbar
        isVisible={toolbarVisible}
        position={toolbarPosition}
        onCommand={executeEditorCommand}
      />
    </div>
  );
};

export default EditorWithBalloonToolbar;

注意事项

  • 需替换代码中的your-api-key为你自己的TinyMCE API Key(基础版可免费申请)。
  • 自定义工具栏的样式、按钮功能可根据需求调整,比如添加链接、列表等更多命令。
  • 若需要更复杂的交互(如文本格式实时预览),可结合TinyMCE的API扩展逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:40:28