我将创建一个带有复制功能的代码块界面,实现点击复制按钮时复制代码内容,并显示成功状态。
思路分析
- 使用jQuery实现复制功能
- 添加视觉反馈:复制成功后显示”已复制”状态
- 1秒后自动恢复初始状态
- 确保代码在各种情况下都能正常复制
最终实现代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>代码复制功能</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
:root {
--bs-dark: #212529;
}
pre.wp-block-code {
position: relative;
background-color: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 0.375rem;
padding: 1rem;
margin: 1rem 0;
overflow-x: auto;
}
pre.wp-block-code code {
display: block;
font-family: 'Courier New', monospace;
font-size: 0.875rem;
color: #212529;
line-height: 1.5;
}
pre.wp-block-code .copy {
display: table;
position: absolute;
right: 1rem;
top: 1rem;
z-index: 1;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 0.25rem;
padding: 0.25rem;
}
pre.wp-block-code .copy .inc-svg {
display: block;
width: 1.5rem;
cursor: pointer;
opacity: 0.8;
transition: opacity 0.2s;
}
pre.wp-block-code .copy .inc-svg:hover {
opacity: 1;
}
pre.wp-block-code .copy .copied {
display: none;
}
pre.wp-block-code .copy .inc-svg svg {
display: block;
width: 100% !important;
height: auto !important;
fill: var(--bs-dark) !important;
}
.code-container {
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
}
h1 {
text-align: center;
margin-bottom: 2rem;
color: #333;
}
.description {
background-color: #e9ecef;
padding: 1rem;
border-radius: 0.375rem;
margin-bottom: 1.5rem;
}
</style>
</head>
<body>
<div class="code-container">
<h1>代码复制功能演示</h1>
<div class="description">
<p>点击代码块右上角的复制按钮,可以复制代码内容。复制成功后按钮会短暂显示"已复制"状态,然后自动恢复。</p>
</div>
<pre class="wp-block-code">
<code>// 示例代码:计算斐波那契数列
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// 打印前10个斐波那契数
for (let i = 0; i < 10; i++) {
console.log(`fibonacci(${i}) = ${fibonacci(i)}`);
}</code>
<div class="copy">
<span class="nocopy inc-svg">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard2-check" viewBox="0 0 16 16">
<path d="M9.5 0a.5.5 0 0 1 .5.5.5.5 0 0 0 .5.5.5.5 0 0 1 .5.5V2a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 2v-.5a.5.5 0 0 1 .5-.5.5.5 0 0 0 .5-.5.5.5 0 0 1 .5-.5z"></path>
<path d="M3 2.5a.5.5 0 0 1 .5-.5H4a.5.5 0 0 0 0-1h-.5A1.5 1.5 0 0 0 2 2.5v12A1.5 1.5 0 0 0 3.5 16h9a1.5 1.5 0 0 0 1.5-1.5v-12A1.5 1.5 0 0 0 12.5 1H12a.5.5 0 0 0 0 1h.5a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5z"></path>
<path d="M10.854 7.854a.5.5 0 0 0-.708-.708L7.5 9.793 6.354 8.646a.5.5 0 1 0-.708.708l1.5 1.5a.5.5 0 0 0 .708 0z"></path>
</svg>
</span>
<span class="copied inc-svg">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard2-check-fill" viewBox="0 0 16 16">
<path d="M10 .5a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5.5.5 0 0 1-.5.5.5.5 0 0 0-.5.5V2a.5.5 0 0 0 .5.5h5A.5.5 0 0 0 11 2v-.5a.5.5 0 0 0-.5-.5.5.5 0 0 1-.5-.5"></path>
<path d="M4.085 1H3.5A1.5 1.5 0 0 0 2 2.5v12A1.5 1.5 0 0 0 3.5 16h9a1.5 1.5 0 0 0 1.5-1.5v-12A1.5 1.5 0 0 0 12.5 1h-.585q.084.236.085.5V2a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 4 2v-.5q.001-.264.085-.5m6.769 6.854-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 9.793l2.646-2.647a.5.5 0 0 1 .708.708"></path>
</svg>
</span>
</div>
</pre>
<pre class="wp-block-code">
<code>// 另一个示例:数组排序函数
function bubbleSort(arr) {
let len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交换元素
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
// 使用示例
let numbers = [64, 34, 25, 12, 22, 11, 90];
console.log("排序前:", numbers);
console.log("排序后:", bubbleSort(numbers));</code>
<div class="copy">
<span class="nocopy inc-svg">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard2-check" viewBox="0 0 16 16">
<path d="M9.5 0a.5.5 0 0 1 .5.5.5.5 0 0 0 .5.5.5.5 0 0 1 .5.5V2a.5.5 0 0 1-.5.5h-5A.5.5 0 0 1 5 2v-.5a.5.5 0 0 1 .5-.5.5.5 0 0 0 .5-.5.5.5 0 0 1 .5-.5z"></path>
<path d="M3 2.5a.5.5 0 0 1 .5-.5H4a.5.5 0 0 0 0-1h-.5A1.5 1.5 0 0 0 2 2.5v12A1.5 1.5 0 0 0 3.5 16h9a1.5 1.5 0 0 0 1.5-1.5v-12A1.5 1.5 0 0 0 12.5 1H12a.5.5 0 0 0 0 1h.5a.5.5 0 0 1 .5.5v12a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5z"></path>
<path d="M10.854 7.854a.5.5 0 0 0-.708-.708L7.5 9.793 6.354 8.646a.5.5 0 1 0-.708.708l1.5 1.5a.5.5 0 0 0 .708 0z"></path>
</svg>
</span>
<span class="copied inc-svg">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard2-check-fill" viewBox="0 0 16 16">
<path d="M10 .5a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5.5.5 0 0 1-.5.5.5.5 0 0 0-.5.5V2a.5.5 0 0 0 .5.5h5A.5.5 0 0 0 11 2v-.5a.5.5 0 0 0-.5-.5.5.5 0 0 1-.5-.5"></path>
<path d="M4.085 1H3.5A1.5 1.5 0 0 0 2 2.5v12A1.5 1.5 0 0 0 3.5 16h9a1.5 1.5 0 0 0 1.5-1.5v-12A1.5 1.5 0 0 0 12.5 1h-.585q.084.236.085.5V2a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 4 2v-.5q.001-.264.085-.5m6.769 6.854-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 9.793l2.646-2.647a.5.5 0 0 1 .708.708"></path>
</svg>
</span>
</div>
</pre>
</div>
<script>
$(document).ready(function() {
// 为所有复制按钮绑定点击事件
$('.copy').on('click', function() {
// 获取当前代码块中的代码文本
const codeText = $(this).closest('pre.wp-block-code').find('code').text();
// 复制文本到剪贴板
copyToClipboard(codeText);
// 切换图标状态
const $nocopy = $(this).find('.nocopy');
const $copied = $(this).find('.copied');
// 隐藏nocopy,显示copied
$nocopy.hide();
$copied.show();
// 1秒后恢复状态
setTimeout(function() {
$copied.hide();
$nocopy.show();
}, 1000);
});
// 复制文本到剪贴板的函数
function copyToClipboard(text) {
// 尝试使用现代剪贴板API
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(function() {
console.log('复制成功!');
}).catch(function(err) {
console.error('复制失败:', err);
fallbackCopy(text);
});
} else {
// 使用备用方法
fallbackCopy(text);
}
}
// 备用复制方法
function fallbackCopy(text) {
const textArea = document.createElement("textarea");
textArea.value = text;
// 避免屏幕滚动
textArea.style.top = "0";
textArea.style.left = "0";
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
if (successful) {
console.log('复制成功!');
} else {
console.error('复制失败');
}
} catch (err) {
console.error('复制失败:', err);
}
document.body.removeChild(textArea);
}
});
</script>
</body>
</html>功能说明
- 复制功能:点击代码块右上角的复制按钮,可以复制代码内容
- 视觉反馈:复制成功后,按钮会短暂显示”已复制”状态
- 自动恢复:1秒后按钮自动恢复为初始状态
- 兼容性:使用了现代剪贴板API,并有备用方案确保在各种浏览器中都能正常工作
这个实现满足了所有要求,并提供了两个示例代码块来演示功能。复制功能使用了两种方法确保兼容性,并提供了清晰的用户反馈。

