一. 复制(copy)、剪切(cut)和粘贴(paste)操作
JavaScript提供了一些事件来处理复制(copy)、剪切(cut)和粘贴(paste)操作,这些事件可用于处理用户在文本框、文本区域或其他可编辑元素中执行的这些操作。JavaScript提供了一些事件来处理复制(copy)、剪切(cut)和粘贴(paste)操作,这些事件可用于处理用户在文本框、文本区域或其他可编辑元素中执行的这些操作。
- copy 事件:当用户执行复制操作时触发。你可以通过监听
copy
事件来执行自定义的处理逻辑,例如修改要复制的文本或数据。
document.addEventListener('copy', function (event) {
// 阻止默认复制操作
event.preventDefault();
// 自定义复制操作,例如修改要复制的文本
const customText = '这是自定义的文本';
event.clipboardData.setData('text/plain', customText);
});
上面示例中,事件对象的clipboardData
属性包含了剪贴板数据。它是一个对象,有以下属性和方法。
Event.clipboardData.setData(type, data)
:修改剪贴板数据,需要指定数据类型。
event.clipboardData.setData()
方法不仅可以用于复制文本,还可以用于复制其他类型的数据,取决于所设置的 MIME 类型。以下是一些常见的 MIME 类型和对应的数据类型示:
// 复制文本:
event.clipboardData.setData('text/plain', '这是文本数据');
// 复制 HTML 格式的文本:
event.clipboardData.setData('text/html', '<p>这是HTML格式的文本</p>');
// 复制图像数据:
event.clipboardData.setData('image/png', 'data:image/png;base64,iVBORw0KG...');
// 复制自定义数据格式:
event.clipboardData.setData('application/my-custom-format', '自定义数据内容');
Event.clipboardData.getData(type)
:获取剪贴板数据,需要指定数据类型。Event.clipboardData.clearData([type])
:清除剪贴板数据,可以指定数据类型。如果不指定类型,将清除所有类型的数据。Event.clipboardData.items
:一个类似数组的对象,包含了所有剪贴项,不过通常只有一个剪贴项。
下面的示例是拦截用户的复制操作,将指定内容放入剪贴板:
let clipboardItems = [];
document.addEventListener('copy', async (e) => {
e.preventDefault();
try {
for (const item of e.clipboardData.items) {
if (!item.type.startsWith('image/')) {
continue;
}
clipboardItems.push(
new ClipboardItem({
[item.type]: item,
})
);
}
if (clipboardItems.length > 0) {
await navigator.clipboard.write(clipboardItems);
console.log('Images copied.');
}
} catch (err) {
console.error(err.name, err.message);
}
});
- cut 事件:当用户执行剪切操作时触发。类似于
copy
事件,你可以监听cut
事件并执行自定义的处理逻辑,例如修改要剪切的文本或数据。
document.addEventListener('cut', function (event) {
// 阻止默认剪切操作
event.preventDefault();
// 自定义剪切操作,例如修改要剪切的文本
const customText = '这是自定义的文本';
event.clipboardData.setData('text/plain', customText);
});
- paste 事件:当用户执行粘贴操作时触发。你可以监听
paste
事件以便在粘贴时执行自定义的处理逻辑,例如检查粘贴的内容或修改粘贴的数据。
document.addEventListener('paste', function (event) {
// 阻止默认粘贴操作
event.preventDefault();
// 获取粘贴的内容
const pastedText = event.clipboardData.getData('text/plain');
// 执行自定义的处理逻辑,例如验证或修改粘贴的内容
console.log('粘贴的内容:', pastedText);
});
通常,我们需要检测粘贴的事件中,是否含有图片文件,需要将图片文件进行上传
document.addEventListener('paste', function (event) {
// 阻止默认粘贴操作
event.preventDefault();
// 获取剪贴板中的项
const clipboardItems = event.clipboardData.items;
// 遍历剪贴板中的项
for (let i = 0; i < clipboardItems.length; i++) {
const item = clipboardItems[i];
// 检查项是否为图片类型
if (item.type.indexOf('image') !== -1) {
// 获取图片数据
const blob = item.getAsFile();
// 处理图片数据,例如显示或上传
// 你可以使用 FileReader 来读取图片数据,然后在页面中显示它
const reader = new FileReader();
reader.onload = function (e) {
const imageDataUrl = e.target.result;
// 在页面中显示图片或执行其他操作
console.log('粘贴的图片数据:', imageDataUrl);
};
reader.readAsDataURL(blob);
} else if (item.type === 'text/plain') {
// 处理文本项目
item.getAsString(function (text) {
// ...
});
} else {
// 处理其他类型的项目 // ...
}
}
});
或者你要求你粘贴的都是图片,并且必须有图片才能执行,可以通过event.clipboardData.files
document.getElementById('editor-post').onpaste = (e) => {
if (!e.clipboardData || !e.clipboardData.files.length) {
return;
}
const files = [...e.clipboardData.files];
// 处理剪贴板中的文件列表
files.forEach((file) => {
console.log('粘贴的文件:', file.name);
// 在这里可以进一步处理文件,例如上传到服务器
});
}
二. Clipboard API
Clipboard API 是一个现代的 Web API,用于访问和操作用户剪贴板(clipboard)中的数据。它提供了更灵活和强大的方式来处理剪贴板操作,包括复制(copy)、粘贴(paste)和剪切(cut)操作。Clipboard API 使开发者能够轻松地与文本、文件和其他多种数据类型进行交互。
Clipboard API 的基本概念和用法:
Clipboard API 中的大多数方法都是异步的,返回 Promise 对象,因此你可以使用 async/await
或 .then()
来处理它们的结果。
-
navigator.clipboard 对象:
Clipboard API 的主要接口是navigator.clipboard
对象。通过这个对象,你可以访问剪贴板并执行复制、粘贴和剪切操作。如果navigator.clipboard
属性返回undefined
,就说明当前浏览器不支持这个 API。因为剪贴板可能包含用户的敏感信息,因此浏览器采取了一些安全措施来保护用户的隐私。
- HTTPS 要求:大多数现代浏览器要求网页必须通过 HTTPS 协议提供,才允许使用 Clipboard API。这是为了确保数据在传输过程中受到加密保护,减少中间人攻击的风险。但是在开发环境中(例如
localhost
),通常允许使用非加密协议。 - 权限要求:对于剪贴板的读取权限(
clipboard-read
),浏览器通常要求用户明确授权给予。这是为了确保用户知情并同意网页可以访问他们的剪贴板数据。因此,在尝试读取剪贴板数据时,浏览器会弹出一个对话框,询问用户是否允许读取。 - 写权限:写入剪贴板的操作通常被自动授权给脚本,因为它通常不涉及隐私问题。脚本可以自由地将文本或文件复制到剪贴板,但读取剪贴板数据需要用户明确授权。
- 复制文本到剪贴板:使用
navigator.clipboard.writeText(text)
方法可以将文本复制到剪贴板。
// 该方法不需要用户许可,但是最好也放在`try...catch`里面防止报错。
// navigator.clipboard.writeText('要复制的文本');
async function copyPageUrl() {
try {
// 使用 Clipboard API 将当前页面的 URL 写入剪贴板
await navigator.clipboard.writeText(location.href);
// 如果成功,记录成功消息
console.log('当前页面的 URL 已复制到剪贴板');
} catch (err) {
// 如果发生错误,记录错误消息
console.error('复制失败: ', err);
}
}
// 在某个按钮点击事件或其他触发操作中调用 copyPageUrl() 函数
// 例如:
// document.getElementById('copyButton').addEventListener('click', copyPageUrl);
- 粘贴剪贴板内容:使用
navigator.clipboard.readText()
方法可以从剪贴板中读取文本内容。用户点击后,浏览器这时会跳出一个对话框,使用try...catch
结构,处理报错。
async function getClipboardContents() {
try {
const text = await navigator.clipboard.readText();
document.getElementById('clipboardContent').textContent = '剪贴板内容: ' + text;
} catch (err) {
console.error('读取剪贴板内容失败: ', err);
}
}
document.getElementById('pasteButton').addEventListener('click', getClipboardContents);
- 复制文件到剪贴板:使用
navigator.clipboard.write
方法可以复制文件到剪贴板。这需要传递一个包含文件的数组。
<body>
<button id="copyButton">复制图像到剪贴板</button>
<script>
async function copyImageToClipboard() {
try {
// 替换为你的图像 URL
const imgURL = 'https://example.com/your-image.png';
// 使用 Fetch API 获取图像数据
const response = await fetch(imgURL);
const blob = await response.blob();
// 创建 ClipboardItem 包含图像数据的对象 例如'image/png'
// const clipboardItem = new ClipboardItem({ 'image/png': blob });
const clipboardItem = new ClipboardItem({ [blob.type]: blob });
// 复制 ClipboardItem 到剪贴板
await navigator.clipboard.write([clipboardItem]);
console.log('图像已复制到剪贴板');
} catch (err) {
console.error('复制图像失败: ', err);
}
}
// 将点击按钮事件与复制函数关联
document.getElementById('copyButton').addEventListener('click', copyImageToClipboard);
</script>
</body>
或者可以不通过fetch
而是直接使用Canvas
将画布上的图像数据转换为Blob
,并且可以进行跨域
// 创建一个 canvas 元素和获取 2D 渲染上下文
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 创建一个 <img> 元素
const img = new Image();
// 可以在外层直接设置 canvas 的宽度和高度,本示例在获取img之后的宽高进行了设置
// canvas.width = 340;
// canvas.height = 340;
// 设置图像的跨域属性为 'Anonymous'
img.crossOrigin = 'Anonymous';
// 设置图像的源 URL(this.mpcodeUrl 是你的图像 URL)
img.src = this.mpcodeUrl;
// 当图像加载完成后执行以下操作
img.onload = () => {
// 获取图像的宽度和高度
const imgWidth = img.width;
const imgHeight = img.height;
// 设置 Canvas 的宽度和高度为图像的实际尺寸
canvas.width = imgWidth;
canvas.height = imgHeight;
// 清空 canvas
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// 将图像绘制到 canvas 上
ctx.drawImage(img, 0, 0);
// 将 canvas 上的图像数据转换为 Blob
canvas.toBlob((blob) => {
// 创建 ClipboardItem 包含 Blob 数据
const data = [
new ClipboardItem({
[blob.type]: blob,
}),
];
// 使用 Clipboard API 复制数据到剪贴板,并使用 .then() 处理异步操作
navigator.clipboard.write(data).then(
() => {
console.log('图像已复制到剪贴板');
},
(err) => {
console.error('复制图像失败: ', err);
}
);
});
};
也可以直接复制文件
// 创建一个包含文本内容的 File 对象
// 创建了一个名为 `example.txt` 的文本文件,并将文本内容设置为 `'file content'`。文件的 MIME 类型被设置为 `'text/plain'`,表示这是一个纯文本文件。
const file = new File(['file content'], 'example.txt', { type: 'text/plain' });
// 使用 Clipboard API 将文件对象写入剪贴板,意味着你可以复制这个文件对象,然后在其他应用程序或页面中粘贴它,以便共享文本内容。意味着你可以复制这个文件对象,然后在其他应用程序或页面中粘贴它,以便共享文本内容。
navigator.clipboard.write([file]);
也可以将同一个剪贴项的多种格式的值,写入剪贴板,一种是文本数据,另一种是二进制数据,供不同的场合粘贴使用。
<body>
<button id="copyButton">复制文本和图像到剪贴板</button>
<script>
document.getElementById('copyButton').addEventListener('click', async () => {
try {
// 创建一个包含文本内容的 Blob 对象
const text = new Blob(['file content'], { type: 'text/plain' });
// 使用 Fetch API 获取图像数据
const response = await fetch('https://example.com/your-image.png');
const imageBlob = await response.blob();
// 创建一个 ClipboardItem,包含文本和图像数据
const clipboardItem = new ClipboardItem({
'text/plain': text, // 文本数据
'image/png': imageBlob // 图像数据
});
// 使用 Clipboard API 将 ClipboardItem 写入剪贴板
await navigator.clipboard.write([clipboardItem]);
console.log('文本和图像已复制到剪贴板');
} catch (err) {
console.error('复制失败: ', err);
}
});
</script>
</body>
- 粘贴剪贴板中的文件:使用
navigator.clipboard.read
方法可以从剪贴板中读取文件。
try {
// 读取剪贴板中的所有剪贴板项
const clipboardItems = await navigator.clipboard.read();
// 遍历每个剪贴板项
for (const clipboardItem of clipboardItems) {
// 打印剪贴板项包含的数据类型
console.log('数据类型:', clipboardItem.types);
// 遍历每个数据类型(type)
for (const type of clipboardItem.types) {
// 获取指定类型的数据(Blob 对象)
const blob = await clipboardItem.getType(type);
// 使用 URL.createObjectURL 创建 Blob 对象的 URL 并打印
const blobURL = URL.createObjectURL(blob);
console.log('数据类型', type);
console.log('数据URL:', blobURL);
// 如果数据类型是图像,可以创建一个图像元素并显示
if (type.startsWith('image/')) {
const img = new Image();
img.src = blobURL;
document.body.appendChild(img);
}
}
}
} catch (err) {
console.error('读取剪贴板内容失败:', err);
}
ClipboardItem 对象表示一个单独的剪贴项,每个剪贴项都拥有ClipboardItem.types
属性和ClipboardItem.getType()
方法。
ClipboardItem.types
属性返回一个数组,里面的成员是该剪贴项可用的 MIME 类型,比如某个剪贴项可以用 HTML 格式粘贴,也可以用纯文本格式粘贴,那么它就有两个 MIME 类型(text/html
和text/plain
)。
ClipboardItem.getType(type)
方法用于读取剪贴项的数据,返回一个 Promise 对象。该方法接受剪贴项的 MIME 类型作为参数,返回该类型的数据,该参数是必需的,否则会报错。
注:什么是MIME类型?
MIME(Multipurpose Internet Mail Extensions)类型是一种标识文档和文件类型的标准方法。它是一种字符串标识符,用于指示文件的内容类型和格式。以下是一些常见的 MIME 类型示例:
text/plain
:纯文本文件。text/html
:HTML 文件。text/css
:CSS 样式表文件。application/javascript
:JavaScript 文件。image/jpeg
:JPEG 格式的图像。image/png
:PNG 格式的图像。audio/mp3
:MP3 音频文件。video/mp4
:MP4 视频文件。application/json
:JSON 数据。
三. Document.execCommand() 方法
Document.execCommand()
方法是一个旧的浏览器 API,用于执行富文本编辑操作,例如文本的复制、粘贴、加粗、斜体、插入链接等。然而,它已被废弃(Deprecated)并不再建议在现代Web应用程序中使用。它的使用方式如下:
document.execCommand(commandName, showUI, value);
commandName
:表示要执行的命令名称,例如 “copy”、“cut”、“paste”、“bold”、“italic” 等。showUI
:一个布尔值,表示是否在执行命令时显示用户界面(如果命令支持)。value
:可选参数,用于某些命令,例如插入链接时,可以传递链接地址。
以下是一个示例,演示如何使用 Document.execCommand()
复制文本到剪贴板:
function copyToClipboard(text) {
const textArea = document.createElement("textarea");
textArea.value = text;
// Append the textarea to the document
document.body.appendChild(textArea);
// Select and copy the text
textArea.select();
document.execCommand('copy');
// Remove the textarea from the document
document.body.removeChild(textArea);
}
// 调用 copyToClipboard 函数
copyToClipboard("要复制的文本内容");
参考: