Chrome扩展开发:实现选中文本触发Popover并保存文本
实现选中文本触发悬浮Popover并保存文本
核心修改思路
- 移除原生模态框(dialog),改为创建跟随选中文本区域定位的悬浮Popover
- 通过选区的
getBoundingClientRect()获取位置,精准定位Popover - 添加保存按钮并绑定消息传递逻辑,实现文本保存
- 优化事件监听,避免重复创建Popover或误关闭
修改后的完整Content.js代码
// Content.js import type { PlasmoCSConfig } from "plasmo" import { useEffect, useState } from "react" const getSelectedText = () => window.getSelection().toString().trim() // 创建并渲染Popover const renderPopover = (selectionRect, selectedText) => { // 先移除已存在的Popover const existingPopover = document.getElementById("text-select-popover") if (existingPopover) { existingPopover.remove() } // 创建Popover容器 const popover = document.createElement("div") popover.id = "text-select-popover" popover.style.cssText = ` position: fixed; top: ${selectionRect.top - 40}px; left: ${selectionRect.left + (selectionRect.width / 2) - 75}px; background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 8px 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); z-index: 999999; display: flex; gap: 8px; align-items: center; ` // 添加文本和保存按钮 const textSpan = document.createElement("span") textSpan.textContent = "保存选中内容" textSpan.style.fontSize = "14px" const saveBtn = document.createElement("button") saveBtn.textContent = "保存" saveBtn.style.cssText = ` padding: 4px 8px; background: #007bff; color: #fff; border: none; border-radius: 2px; cursor: pointer; font-size: 14px; ` // 保存按钮点击事件:发送消息到后台 saveBtn.addEventListener("click", async () => { await chrome.runtime.sendMessage({ type: "SAVE_SELECTED_TEXT", text: selectedText }) popover.remove() // 保存后关闭Popover }) popover.appendChild(textSpan) popover.appendChild(saveBtn) document.body.appendChild(popover) // 点击页面其他区域关闭Popover const closePopover = (e) => { if (!popover.contains(e.target)) { popover.remove() document.removeEventListener("click", closePopover) } } document.addEventListener("click", closePopover) } // 监听文本选中事件 useEffect(() => { const handleSelection = () => { const selectedText = getSelectedText() if (selectedText) { const selection = window.getSelection() const range = selection.getRangeAt(0) const selectionRect = range.getBoundingClientRect() renderPopover(selectionRect, selectedText) } else { // 无选中时移除Popover const existingPopover = document.getElementById("text-select-popover") existingPopover?.remove() } } // 监听鼠标松开(选中文本后触发) document.addEventListener("mouseup", handleSelection) // 监听键盘选中文本(比如Ctrl+A) document.addEventListener("keyup", handleSelection) return () => { document.removeEventListener("mouseup", handleSelection) document.removeEventListener("keyup", handleSelection) } }, [])
关键细节说明
- 定位逻辑:通过
range.getBoundingClientRect()获取选中文本的矩形区域,将Popover定位在选区上方居中位置,避免遮挡选中内容 - 样式优化:添加阴影、圆角和合适的层级(z-index),确保Popover在页面最上层且视觉友好
- 事件优化:使用
mouseup和keyup监听选中文本,比原有的click更精准;添加Popover外点击关闭逻辑,同时避免点击Popover内部时误关闭 - 重复创建处理:每次创建前先移除已存在的Popover,避免页面出现多个悬浮框
后续补充
- 若需要更复杂的Popover样式,可以将CSS抽离到单独的样式文件中,通过Plasmo的
css配置引入 - 保存文本的后台逻辑(比如存储到chrome.storage)需要在
background.js中监听SAVE_SELECTED_TEXT类型的消息并处理
内容的提问来源于stack exchange,提问作者dmk
相关产品推荐
相关产品推荐

