封装一个美观、实用的备忘录弹出层函数,包含动画效果、样式隔离、快捷键保存等功能。以下是完整的实现:
/**
* 备忘录弹出层函数
* @param {string} [initialContent=''] - 初始文本内容
* @param {function} [onSave=null] - 保存回调函数
* @returns {object} 返回包含关闭方法的对象
*/
function createMemoPopup(initialContent = '', onSave = null) {
// 生成随机ID用于样式隔离
const memoId = 'memo-popup-' + Math.random().toString(36).substr(2, 9);
// 创建DOM元素
const overlay = document.createElement('div');
const popup = document.createElement('div');
const textarea = document.createElement('textarea');
const closeBtn = document.createElement('button');
const saveBtn = document.createElement('button');
const hintText = document.createElement('div');
const header = document.createElement('div');
// 设置元素属性
textarea.value = initialContent;
textarea.placeholder = '记录您的想法或待办事项...';
closeBtn.innerHTML = '×';
saveBtn.textContent = '保存';
hintText.textContent = '提示: Ctrl+S 保存';
// 构建DOM结构
header.appendChild(closeBtn);
header.appendChild(hintText);
popup.appendChild(header);
popup.appendChild(textarea);
popup.appendChild(saveBtn);
overlay.appendChild(popup);
// 添加到body
document.body.appendChild(overlay);
// 添加样式
const style = document.createElement('style');
style.textContent = `
.${memoId}-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
transition: opacity 0.3s ease;
backdrop-filter: blur(3px);
}
.${memoId}-popup {
width: 90%;
max-width: 600px;
background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
overflow: hidden;
transform: translateY(-20px);
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
border: 1px solid rgba(255, 255, 255, 0.3);
}
.${memoId}-popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);
color: white;
}
.${memoId}-close-btn {
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
transition: transform 0.2s;
padding: 0 10px;
}
.${memoId}-close-btn:hover {
transform: scale(1.2);
}
.${memoId}-hint {
font-size: 13px;
opacity: 0.8;
}
.${memoId}-textarea {
width: 100%;
height: 300px;
padding: 20px;
border: none;
resize: none;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
line-height: 1.6;
background-color: rgba(255, 255, 255, 0.8);
color: #333;
box-sizing: border-box;
transition: background-color 0.3s;
}
.${memoId}-textarea:focus {
outline: none;
background-color: white;
}
.${memoId}-save-btn {
display: block;
width: 100%;
padding: 12px;
background: linear-gradient(to right, #4facfe 0%, #00f2fe 100%);
color: white;
border: none;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
}
.${memoId}-save-btn:hover {
background: linear-gradient(to right, #3a7bd5 0%, #00d2ff 100%);
}
@media (max-width: 600px) {
.${memoId}-popup {
width: 95%;
}
.${memoId}-textarea {
height: 200px;
}
}
`;
document.head.appendChild(style);
// 添加类名
overlay.className = `${memoId}-overlay`;
popup.className = `${memoId}-popup`;
header.className = `${memoId}-popup-header`;
closeBtn.className = `${memoId}-close-btn`;
hintText.className = `${memoId}-hint`;
textarea.className = `${memoId}-textarea`;
saveBtn.className = `${memoId}-save-btn`;
// 显示动画
setTimeout(() => {
overlay.style.opacity = '1';
popup.style.transform = 'translateY(0)';
}, 10);
// 关闭函数
function close() {
overlay.style.opacity = '0';
popup.style.transform = 'translateY(-20px)';
setTimeout(() => {
document.body.removeChild(overlay);
document.head.removeChild(style);
}, 300);
}
// 保存函数
function save() {
if (typeof onSave === 'function') {
onSave(textarea.value);
}
// 添加保存动画反馈
saveBtn.textContent = '✓ 已保存';
setTimeout(() => {
saveBtn.textContent = '保存';
}, 1500);
}
// 事件监听
closeBtn.addEventListener('click', close);
saveBtn.addEventListener('click', save);
// 快捷键保存
textarea.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
e.preventDefault();
save();
}
});
// 点击遮罩层关闭
overlay.addEventListener('click', (e) => {
if (e.target === overlay) {
close();
}
});
// 自动聚焦到文本域
setTimeout(() => {
textarea.focus();
}, 350);
// 返回关闭方法
return {
close: close,
getContent: () => textarea.value,
setContent: (content) => { textarea.value = content; }
};
}
// 使用示例
// const memo = createMemoPopup('初始内容', (content) => {
// console.log('保存的内容:', content);
// // 这里可以添加保存到本地存储或其他逻辑
// });功能特点:
- 样式隔离:使用随机生成的类名前缀,确保样式不会与其他元素冲突
- 响应式设计:适配不同屏幕尺寸,在手机上自动调整高度
动画效果:
- 淡入淡出的遮罩层
- 弹窗滑入动画
- 保存按钮的反馈动画
- 快捷键支持:支持 Ctrl+S 保存内容
美观UI:
- 渐变色标题栏
- 毛玻璃遮罩效果
- 精心设计的间距和字体
完整API:
- 可以获取/设置内容
- 可以手动关闭弹窗
- 支持保存回调
用户体验优化:
- 自动聚焦到文本域
- 清晰的提示信息
- 合理的过渡效果
您可以通过调用 createMemoPopup() 函数来使用这个弹窗,传入初始内容和保存回调函数即可。
需支付 5元 阅读剩余内容