JS实现复制粘贴文字及图片功能

 更新时间:2024年07月17日 08:57:21   作者:Code技术分享  
Clipboard API 是一组用于在浏览器中操作剪贴板的 JavaScript API,它允许开发者在网页上读取和写入剪贴板内容,实现复制、剪切和粘贴等功能,这篇文章主要介绍了JS实现复制粘贴文字及图片功能,需要的朋友可以参考下

一. 基于 Clipboard API 复制文字(推荐)

基本概念

Clipboard API 是一组用于在浏览器中操作剪贴板的 JavaScript API,它允许开发者在网页上读取和写入剪贴板内容,实现复制、剪切和粘贴等功能。Clipboard API 提供了一种在网页上读取和写入剪贴板内容的方式,包括文本、图像和其他类型的数据。Clipboard API 适用于需要与用户剪贴板进行交互的网页应用,如实现一键复制、粘贴功能,或者在用户复制特定内容时自动添加额外信息等。

https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard_API

主要方法

Clipboard API 提供了几个关键的方法来实现剪贴板的读写操作:

  • navigator.clipboard.writeText(text):将给定的文本复制到剪贴板。这是一个异步方法,会返回一个 Promise 对象,成功时 Promise 会被解析,失败时会被拒绝。
  • navigator.clipboard.readText():从剪贴板读取文本内容。这也是一个异步方法,返回一个 Promise 对象,解析后提供剪贴板中的文本内容。
  • navigator.clipboard.write(data):写入更复杂的数据类型到剪贴板,如文件、图像等。data 参数是一个包含 ClipboardItem 对象的数组,每个 ClipboardItem 对象代表剪贴板中的一项数据。这也是一个异步方法,返回一个 Promise 对象。
  • navigator.clipboard.read():从剪贴板读取更复杂的数据类型,如文件、图像等。这个方法会返回一个 Promise 对象,解析后提供一个包含 ClipboardItem 对象的数组。

使用限制

  • 用户授权:由于安全和隐私的考虑,浏览器在使用 Clipboard API 时通常需要用户授权。例如,在尝试从剪贴板读取或写入数据时,浏览器可能会要求用户明确允许。
  • 安全上下文:Clipboard API 只能在安全的环境中操作剪贴板,如 HTTPS 页面、localhost本机下。
  • 浏览器兼容性:虽然大多数现代浏览器都支持 Clipboard API,但仍有部分旧版浏览器可能不支持。因此,在使用时需要考虑浏览器的兼容性。

实际应用示例

<template>
    <el-button type="primary" @click="handleCopy">复制文本</el-button>
    <div>{{ message }}</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const message = ref('复制的内容')
const handleCopy = () => {
    navigator.clipboard
        .writeText(message.value)
        .then(() => {
            ElMessage({
                message: '复制成功',
                type: 'success',
            })
        })
        .catch((err) => {
            console.error('复制失败:', err)
            ElMessage({
                message: '复制失败',
                type: 'error',
            })
        })
}
</script>

二、基于 document.execCommand('copy')

document.execCommand('copy') 是一个在网页上执行复制操作的旧式API,属于 Web API 的一部分,用于在不需要用户交互(如点击或按键)的情况下,通过脚本复制文本到剪贴板。然而,这个API在现代Web开发中已经被视为过时(deprecated),并在许多现代浏览器中受到限制或不再支持,尤其是在没有用户明确交互的情况下。

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand

缺陷

  • 只能操作input, textarea或具有contenteditable属性的元素
  • execCommand 是同步操作,如果复制/粘贴大量数据,可能会导致页面出现卡顿现象,影响用户体验。
  • 它只能将选中的内容复制到剪贴板,无法向剪贴板任意写入内容
  • 有些浏览器还会跳出提示框,要求用户许可,这时在用户做出选择前,页面会失去响应。

实际应用示例

<template>
    <el-button type="primary" @click="handleCopy2">复制文本2</el-button>
    <div>{{ message }}</div>
</template>
<script setup>
import {
    copyText,
    copyImage,
    imageUrlToBase64,
    parseBase64,
} from './common/copy'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const message = ref('复制的内容')
const handleCopy2 = () => {
    // 动态创建 textarea 标签
    const textarea = document.createElement('textarea')
    // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
    textarea.readOnly = 'readonly'
    textarea.style.position = 'absolute'
    textarea.style.left = '-9999px'
    textarea.style.opacity = '0'
    // 将要 copy 的值赋给 textarea 标签的 value 属性
    textarea.value = message.value
    // 将 textarea 插入到 body 中
    document.body.appendChild(textarea)
    // 选中值并复制
    textarea.select()
    const result = document.execCommand('Copy')
    if (result) {
        ElMessage({
            message: '复制成功',
            type: 'success',
        })
    }
    document.body.removeChild(textarea)
}
</script>

说明

clipboard.js 底层也是基于 document.execCommand去实现的

function createFakeElement(value) {
  var isRTL = document.documentElement.getAttribute('dir') === 'rtl';
  var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS
  fakeElement.style.fontSize = '12pt'; // Reset box model
  fakeElement.style.border = '0';
  fakeElement.style.padding = '0';
  fakeElement.style.margin = '0'; // Move element out of screen horizontally
  fakeElement.style.position = 'absolute';
  fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically
  var yPosition = window.pageYOffset || document.documentElement.scrollTop;
  fakeElement.style.top = "".concat(yPosition, "px");
  fakeElement.setAttribute('readonly', '');
  fakeElement.value = value;
  return fakeElement;
}
var fakeCopyAction = function fakeCopyAction(value, options) {
  var fakeElement = createFakeElement(value);
  options.container.appendChild(fakeElement);
  var selectedText = select_default()(fakeElement);
  command('copy');
  fakeElement.remove();
  return selectedText;
};

三、复制图片功能

<template>
    <el-button type="primary" @click="handleCopyImage">复制图片</el-button>
    <div>{{ message }}</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const message = ref('复制的内容')
const handleCopyImage = async () => {
    //具体看下面的封装
    await copyImage('https://cn.vitejs.dev/logo-with-shadow.png')
    ElMessage({
        message: '复制成功',
        type: 'success',
    })
}
</script>

四、封装

/**
 * 图片转base64
 * @param {string} 图片地址
 * @returns
 */
export const imageUrlToBase64 = (imageUrl) => {
    return new Promise((resolve, reject) => {
        let image = new Image()
        image.setAttribute('crossOrigin', 'Anonymous')
        image.src = imageUrl
        image.onload = function () {
            const canvas = document.createElement('canvas')
            canvas.width = image.width
            canvas.height = image.height
            const context = canvas.getContext('2d')
            context.drawImage(image, 0, 0, image.width, image.height)
            const base64Str = canvas.toDataURL('image/png')
            resolve(base64Str)
        }
        image.onerror = function (e) {
            reject(e)
        }
    })
}
/**
 * 转换base64
 * @param {string} base64
 * @returns
 */
export function parseBase64(base64) {
    let re = new RegExp('data:(?<type>.*?);base64,(?<data>.*)')
    let res = re.exec(base64)
    if (res) {
        return {
            type: res.groups.type,
            ext: res.groups.type.split('/').slice(-1)[0],
            data: res.groups.data,
        }
    }
}
/**
 * 复制文字
 * @param {string} text  要复制的文本
 * @returns {boolean} true/false
 */
export const copyText = async (text) => {
    if (navigator && navigator.clipboard) {
        await navigator.clipboard.writeText(text)
        return true
    }
    // 动态创建 textarea 标签
    const textarea = document.createElement('textarea')
    // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
    textarea.readOnly = 'readonly'
    textarea.style.position = 'absolute'
    textarea.style.left = '-9999px'
    textarea.style.opacity = '0'
    // 将要 copy 的值赋给 textarea 标签的 value 属性
    textarea.value = text
    // 将 textarea 插入到 body 中
    document.body.appendChild(textarea)
    // 选中值并复制
    textarea.select()
    const result = document.execCommand('Copy')
    document.body.removeChild(textarea)
    return result
}
/**
 * 复制图片
 * @param {string} imageUrl 图片地址
 * @param {boolean} isBase64 是否是base64
 */
export const copyImage = async (imageUrl, isBase64 = false) => {
    let base64Url = ''
    if (!isBase64) {
        base64Url = await imageUrlToBase64(imageUrl)
    } else base64Url = imageUrl
    const parsedBase64 = parseBase64(base64Url)
    let type = parsedBase64.type
    //将base64转为Blob类型
    let bytes = atob(parsedBase64.data)
    let ab = new ArrayBuffer(bytes.length)
    let ua = new Uint8Array(ab)
    for (let i = 0; i < bytes.length; i++) {
        ua[i] = bytes.charCodeAt(i)
    }
    let blob = new Blob([ab], { type })
    navigator.clipboard.write([new ClipboardItem({ [type]: blob })])
}

到此这篇关于JS实现复制粘贴文字以及图片的文章就介绍到这了,更多相关js复制粘贴文字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS中showModalDialog关闭子窗口刷新主窗口用法详解

    JS中showModalDialog关闭子窗口刷新主窗口用法详解

    这篇文章主要介绍了JS中showModalDialog关闭子窗口刷新主窗口用法,结合具体实例形式较为详细的分析了showModalDialog常见用法与相关使用技巧,需要的朋友可以参考下
    2017-03-03
  • javascript 制作坦克大战游戏初步 图片与代码

    javascript 制作坦克大战游戏初步 图片与代码

    javascript 制作坦克大战游戏初步 图片与代码...
    2007-11-11
  • 详解webpack-dev-server使用http-proxy解决跨域问题

    详解webpack-dev-server使用http-proxy解决跨域问题

    这篇文章主要介绍了详解webpack-dev-server使用http-proxy解决跨域问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • uniapp实现app自动更新详细步骤

    uniapp实现app自动更新详细步骤

    这篇文章主要给大家介绍了关于uniapp实现app自动更新的详细步骤,文中给出了详细的代码示例以及图文教程,对大家学习或者使用uniapp具有一定的参考学习价值,需要的朋友可以参考下
    2023-08-08
  • Javascript实现的常用算法(如冒泡、快速、鸽巢、奇偶等)

    Javascript实现的常用算法(如冒泡、快速、鸽巢、奇偶等)

    这篇文章主要介绍了Javascript实现的常用算法,如冒泡、快速、鸽巢、选择、木桶、奇偶等,需要的朋友可以参考下
    2014-04-04
  • JavaScript实现拖动模态框

    JavaScript实现拖动模态框

    这篇文章主要为大家详细介绍了JavaScript实现拖动模态框,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • JavaScript实现中文数字转为阿拉伯数字的方法

    JavaScript实现中文数字转为阿拉伯数字的方法

    在JavaScript编程中,实现阿拉伯数字和中文数字之间的互相转换是一个常见的需求,这涉及到字符串处理和数值计算,本文将详细介绍如何利用JavaScript实现这一功能,需要的朋友可以参考下
    2025-03-03
  • electron的webview和内嵌网页通信的方法

    electron的webview和内嵌网页通信的方法

    在 Electron 的世界里,webview 标签相当于一个小盒子,里面可以装一个完整的网页,就像一个迷你浏览器,这篇文章主要介绍了electron的webview和内嵌网页如何通信,需要的朋友可以参考下
    2024-04-04
  • 配置eslint规范项目代码风格

    配置eslint规范项目代码风格

    这篇文章主要介绍了配置eslint规范项目代码风格,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • Three.js实现3D乒乓球小游戏(物理效果)

    Three.js实现3D乒乓球小游戏(物理效果)

    本文将使用React Three Fiber 和 Cannon.js 来实现一个具有物理特性的乒乓球小游戏,使用 React Three Fiber 搭建基础三维场景、如何使用新技术栈给场景中对象的添加物理特性等,最后利用上述知识点,将开发一个简单的乒乓球小游戏,需要的朋友可以参考下
    2023-03-03

最新评论