基于HTML的悬窗可拖动记事本
这款记事本全部使用HTML+CSS+JS实现,可以在浏览器中实现悬浮可拖动的记事本,所有内容存储在浏览器中,清除缓存后将会丢失记事本内容
效果展示
实现代码
<div id="draggableWindowNote" class="draggableNote">
<div id="dragHeaderNote" class="drag-headerNote">
<span>Note</span>
<div id="addNote" style="font-size: 19px;
cursor: pointer;
position: absolute;
right: 0;
margin-right: 10px;">+</div>
</div>
<div id="noteApp">
<div class="note-header">
</div>
<div id="noteList"></div>
<div id="noteModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<span class="close" style="float: left;">×</span>
<div
style="position: absolute; right: 0; top: 0; height: 100%; width: 78px; background-color: transparent;">
</div>
</div>
<textarea id="noteEditor"></textarea>
<button id="saveNote"
style="cursor: pointer;border: none;background: transparent;font-weight: 900;">保存</button>
<button id="deleteNote" class="delete-btn"
style="cursor: pointer;border: none;background: transparent;font-weight: 900;">删除</button>
</div>
</div>
</div>
</div>
<!-- 沂霖博客 https://nanwish.love -->
<script>
// 拖动逻辑
const draggableWindow = document.getElementById('draggableWindowNote');
const dragHeader = document.getElementById('dragHeaderNote');
let isDragging = false;
let offsetX, offsetY;
dragHeader.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggableWindow.offsetLeft;
offsetY = e.clientY - draggableWindow.offsetTop;
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
draggableWindow.style.left = (e.clientX - offsetX) + 'px';
draggableWindow.style.top = (e.clientY - offsetY) + 'px';
}
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
</script>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background-color: #575757;
color: #ffffff;
}
.draggableNote {
position: absolute;
width: 200px;
background-color: #242424;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(168, 168, 168, 0.1);
z-index: 1000;
}
.drag-headerNote {
background-color: #000000;
border-bottom: 1px solid #1be409;
cursor: move;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
}
.chinaImg {
width: 100%;
max-width: 100%;
max-height: 128px;
}
#noteApp {
max-width: 600px;
margin: 0 auto;
}
.note-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.note-item {
padding: 3px;
border-bottom: 1px solid #eee;
cursor: pointer;
}
.note-item:hover {
background-color: #f5f5f5;
}
.note-title {
font-weight: bold;
}
.note-content {
display: none;
margin-top: 10px;
padding: 10px;
background-color: #f9f9f9;
border-radius: 3px;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 1px;
}
.modal-content {
background-color: transparent;
margin: 15% auto;
width: 80%;
max-width: 500px;
}
#noteEditor {
width: 100%;
height: 200px;
margin-bottom: 10px;
border-radius: 17px;
border: none;
padding: 8px;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
position: relative;
z-index: 9;
}
.close:hover {
color: black;
}
.delete-btn {
color: rgb(255, 0, 0);
}
.modal-header {
padding: 10px;
cursor: move;
position: relative;
display: flex;
flex-direction: row-reverse;
align-items: center;
justify-content: flex-start;
}
</style>
<script>
let notes = JSON.parse(localStorage.getItem('notes')) || [];
let currentNoteIndex = -1;
const noteList = document.getElementById('noteList');
const noteModal = document.getElementById('noteModal');
const noteEditor = document.getElementById('noteEditor');
const addNoteBtn = document.getElementById('addNote');
const saveNoteBtn = document.getElementById('saveNote');
const deleteNoteBtn = document.getElementById('deleteNote');
const closeBtn = document.querySelector('.close');
function renderNotes() {
noteList.innerHTML = '';
notes.forEach((note, index) => {
const noteItem = document.createElement('div');
noteItem.className = 'note-item';
// 截取前10个字符作为标题
const title = note.content.substring(0, 10);
noteItem.innerHTML = `
<div class="note-title">${title}...</div>
<div class="note-content">${note.content}</div>
`;
noteItem.addEventListener('click', () => {
currentNoteIndex = index;
noteEditor.value = note.content;
noteModal.style.display = 'block';
});
noteList.appendChild(noteItem);
});
}
// 新增笔记
addNoteBtn.addEventListener('click', () => {
currentNoteIndex = -1;
noteEditor.value = '';
noteModal.style.display = 'block';
});
// 保存笔记
saveNoteBtn.addEventListener('click', () => {
const content = noteEditor.value.trim();
if (content) {
if (currentNoteIndex === -1) {
// 新增
notes.push({ content });
} else {
// 编辑
notes[currentNoteIndex].content = content;
}
localStorage.setItem('notes', JSON.stringify(notes));
renderNotes();
noteModal.style.display = 'none';
}
});
// 删除笔记
deleteNoteBtn.addEventListener('click', () => {
if (currentNoteIndex !== -1) {
notes.splice(currentNoteIndex, 1);
localStorage.setItem('notes', JSON.stringify(notes));
renderNotes();
noteModal.style.display = 'none';
}
});
// 关闭模态框
closeBtn.addEventListener('click', () => {
noteModal.style.display = 'none';
});
// 初始化
renderNotes();
// 模态框拖动功能
const modal = document.getElementById('noteModal');
const modalHeader = document.querySelector('.modal-header');
let isModalDragging = false;
let modalOffsetX, modalOffsetY;
modalHeader.addEventListener('mousedown', (e) => {
isModalDragging = true;
modalOffsetX = e.clientX - modal.offsetLeft;
modalOffsetY = e.clientY - modal.offsetTop;
});
document.addEventListener('mousemove', (e) => {
if (isModalDragging) {
modal.style.left = (e.clientX - modalOffsetX) + 'px';
modal.style.top = (e.clientY - modalOffsetY) + 'px';
}
});
document.addEventListener('mouseup', () => {
isModalDragging = false;
});
</script>