选中文本,并弹出复制按钮,点击复制,复制内容

510 阅读3分钟

大家好我是辉子,遇到有用的东西就记录下来,也希望和您成为朋友。关注 公众号: 【罗米笔记】,有更好的笔记会及时更新,

image.png 在翻看百度百科的时候,选中一段文字,有很多弹出层,当然有些是浏览器插件制作的。但是有一个复制功能,却是网站本身的效果。 当然这个小点大部分人不会去关注。但是看到了,今天就实现一下。下面是基于vue3示例

  1. 添加需要的样式及示例文字 ::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>
  1. 需要2个监听事件,一个是鼠标抬起,一个是选择文字触发的事件
let str = "";

onMounted(() => {
  document.addEventListener("mouseup", handleMouseUp);
  document.addEventListener("selectionchange", handleSelectionChange);
});

function handleMouseUp(){}
function handleSelectionChange() {}
  1. 实现handleSelectionChange对应的功能,选中的目的是为了获取文字
  function handleSelectionChange() {
      const selection = window.getSelection();
      if (selection && selection.toString().length !== 0) {
        str = selection.toString();
      }
  }
  1. 实现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);
  }
}
  1. 基本效果就已经实现,但是现在会出现多次复制按钮, 所以要在每次再次选取的时候重置 , 所以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();
  }
}
  1. 上面的小功能基本就结束了。最终效果

image.png 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>