大家好我是辉子,遇到有用的东西就记录下来,也希望和您成为朋友。关注 公众号: 【罗米笔记】,有更好的笔记会及时更新,
在翻看百度百科的时候,选中一段文字,有很多弹出层,当然有些是浏览器插件制作的。但是有一个复制功能,却是网站本身的效果。
当然这个小点大部分人不会去关注。但是看到了,今天就实现一下。下面是基于vue3示例
- 添加需要的样式及示例文字 ::selection 文字选中颜色
<template>
<div id="page">
<div class="content">
在这个示例中,当页面加载完成后,JavaScript代码会监听复制按钮的点击事件。当按钮被点击时,它会创建一个临时的textarea元素,设置其值为要复制的文本,并将其添加到DOM中。然后,它会聚焦这个textarea,选中其中的文本,并尝试使用document.execCommand('copy')来执行复制操作。如果复制成功,它会显示一个成功的提示;如果失败,它会显示一个错误消息。最后,它会从DOM中移除临时创建的textarea元素。
</div>
</div>
</template>
<style scoped lang="scss">
#page {
width: 100%;
height: 100vh;
position: relative;
}
::selection {
background-color: cyan;
}
</style>
<style>
.bubble {
position: absolute;
z-index: 999;
padding: 5px 10px;
border-radius: 5px;
background-color: #f1f1f1;
cursor: pointer;
}
</style>
- 需要2个监听事件,一个是鼠标抬起,一个是选择文字触发的事件
let str = "";
onMounted(() => {
document.addEventListener("mouseup", handleMouseUp);
document.addEventListener("selectionchange", handleSelectionChange);
});
function handleMouseUp(){}
function handleSelectionChange() {}
- 实现handleSelectionChange对应的功能,选中的目的是为了获取文字
function handleSelectionChange() {
const selection = window.getSelection();
if (selection && selection.toString().length !== 0) {
str = selection.toString();
}
}
- 实现handleMouseUp功能 , 主要是为了设置按钮的位置及弹出
function handleMouseUp() {
if (str.length !== 0) {
getSelectedTextAndPosition(str);
str = "";
}
}
// 获取选中文本及位置
function getSelectedTextAndPosition(str: string) {
const selection = window.getSelection();
if (selection && !selection.isCollapsed) {
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// 计算气泡框的位置
const bubbleTop = rect.top + rect.height / 2 - 20 / 2;
const bubbleLeft = rect.left + rect.width / 2 - 100 / 2;
// 创建气泡框
const bubble = document.createElement("button");
bubble.className = "bubble";
bubble.textContent = "复制";
bubble.style.top = `${bubbleTop}px`;
bubble.style.left = `${bubbleLeft}px`;
bubble.onclick = async function () {
await navigator.clipboard.writeText(str);
alert("复制成功");
};
document.body.appendChild(bubble);
}
}
- 基本效果就已经实现,但是现在会出现多次复制按钮, 所以要在每次再次选取的时候重置 , 所以handleSelectionChange 函数变成了这样
function handleSelectionChange() {
const bubble = document.querySelector(".bubble");
if (bubble !== null) {
bubble.remove();
}
const selection = window.getSelection();
if (selection && selection.toString().length !== 0) {
str = selection.toString();
}
}
- 上面的小功能基本就结束了。最终效果
7. vue3 示例完整代码
<template>
<div id="page">
<div class="content">
在这个示例中,当页面加载完成后,JavaScript代码会监听复制按钮的点击事件。当按钮被点击时,它会创建一个临时的textarea元素,设置其值为要复制的文本,并将其添加到DOM中。然后,它会聚焦这个textarea,选中其中的文本,并尝试使用document.execCommand('copy')来执行复制操作。如果复制成功,它会显示一个成功的提示;如果失败,它会显示一个错误消息。最后,它会从DOM中移除临时创建的textarea元素。
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted } from "vue";
let str = "";
onMounted(() => {
document.addEventListener("mouseup", handleMouseUp);
document.addEventListener("selectionchange", handleSelectionChange);
});
function handleMouseUp() {
if (str.length !== 0) {
getSelectedTextAndPosition(str);
str = "";
}
}
function handleSelectionChange() {
const bubble = document.querySelector(".bubble");
if (bubble !== null) {
bubble.remove();
}
const selection = window.getSelection();
if (selection && selection.toString().length !== 0) {
str = selection.toString();
}
}
// 获取选中文本及位置
function getSelectedTextAndPosition(str: string) {
const selection = window.getSelection();
if (selection && !selection.isCollapsed) {
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// 计算气泡框的位置
const bubbleTop = rect.top + rect.height / 2 - 20 / 2;
const bubbleLeft = rect.left + rect.width / 2 - 100 / 2;
// 创建气泡框
const bubble = document.createElement("button");
bubble.className = "bubble";
bubble.textContent = "复制";
bubble.style.top = `${bubbleTop}px`;
bubble.style.left = `${bubbleLeft}px`;
bubble.onclick = async function () {
await navigator.clipboard.writeText(str);
alert("复制成功");
};
document.body.appendChild(bubble);
}
}
</script>
<style scoped lang="scss">
#page {
width: 100%;
height: 100vh;
position: relative;
}
::selection {
background-color: cyan;
}
</style>
<style>
.bubble {
position: absolute;
z-index: 999;
padding: 5px 10px;
border-radius: 5px;
background-color: #f1f1f1;
cursor: pointer;
}
</style>