核心实现原理
监听选中事件:通过 CodeMirror 的 selectionChange 事件监听文本选中状态。
计算菜单位置:根据选中文本的坐标动态定位悬浮菜单。
渲染自定义菜单:创建 DOM 元素作为悬浮菜单,绑定交互事件。
完整代码
点击查看全文
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>CodeMirror 悬浮菜单</title> <link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/codemirror.css"> <style> /* 悬浮菜单样式 */ .code-menu { position: absolute; background: white; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); z-index: 100; padding: 4px; display: none; } .code-menu button { display: block; width: 100%; padding: 6px 12px; background: none; border: none; text-align: left; cursor: pointer; } .code-menu button:hover { background: #f0f0f0; } </style> </head> <body> <textarea id="editor">// 选中代码试试看 function hello() { console.log("Hello World"); }</textarea> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/codemirror/codemirror.5.26.js"></script> <script> // 初始化编辑器 const editor = CodeMirror.fromTextArea(document.getElementById('editor'), { lineNumbers: true, mode: 'javascript', value: '// 测试选中这段代码\nfunction test() { console.log("Hello"); }' }); // 创建菜单 const menu = document.createElement('div'); menu.className = 'code-menu'; document.body.appendChild(menu); // 菜单操作项 ['复制', '注释', '格式化'].forEach(text => { const btn = document.createElement('button'); btn.textContent = text; btn.style.display = 'block'; btn.onclick = () => { if (text === '复制') handleCopy(); if (text === '注释') handleComment(); if (text === '格式化') handleFormat(); }; menu.appendChild(btn); }); // 修复事件监听 editor.on('cursorActivity', (cm) => { const selection = cm.getSelection(); selection ? showMenu(cm) : hideMenu(); }); // 优化定位逻辑 function showMenu(cm) { const cursor = cm.getCursor('to'); const coords = cm.cursorCoords(cursor, 'page'); const scroll = cm.getScrollInfo(); menu.style.display = 'block'; menu.style.top = `${coords.top + scroll.top - 15}px`; // 微调垂直位置 menu.style.left = `${coords.right + scroll.left + 10}px`; } function hideMenu() { menu.style.display = 'none'; } // 点击外部关闭 document.addEventListener('click', (e) => { if (!menu.contains(e.target) && !cm.getWrapperElement().contains(e.target)) { hideMenu(); } }); // 示例操作函数 function handleCopy() { const selection = editor.getSelection(); navigator.clipboard.writeText(selection); hideMenu(); } function handleComment() { const selection = editor.getSelection(); editor.replaceSelection(`/* ${selection} */`); } function handleFormat() { const selection = editor.getSelection(); // 此处可调用 Prettier 等格式化工具 alert('格式化功能需集成格式化库'); } </script> </body> </html>
网友回复
python如何实现torrent的服务端进行文件分发p2p下载?
如何在浏览器中录制摄像头和麦克风数据为mp4视频保存下载本地?
go如何编写一个类似docker的linux的虚拟容器?
python如何写一个bittorrent的种子下载客户端?
ai能通过看一个网页的交互过程视频自主模仿复制网页编写代码吗?
ai先写功能代码通过chrome mcp来进行测试功能最后ai美化页面这个流程能行吗?
vue在手机端上下拖拽元素的时候如何禁止父元素及body的滚动导致无法拖拽完成?
使用tailwindcss如何去掉响应式自适应?
有没有直接在浏览器中运行的离线linux系统?
nginx如何保留post或get数据进行url重定向?