基于HTML的悬窗可拖动记事本

基于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;">&times;</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>
相关推荐
CCF_NOI.1 小时前
谷歌浏览器深入用法全解析:解锁高效网络之旅
大数据·运维·服务器·前端·计算机·谷歌
paopaokaka_luck4 小时前
基于SpringBoot+Uniapp的健身饮食小程序(协同过滤算法、地图组件)
前端·javascript·vue.js·spring boot·后端·小程序·uni-app
患得患失9495 小时前
【前端】【vscode】【.vscode/settings.json】为单个项目配置自动格式化和开发环境
前端·vscode·json
飛_5 小时前
解决VSCode无法加载Json架构问题
java·服务器·前端
YGY Webgis糕手之路7 小时前
OpenLayers 综合案例-轨迹回放
前端·经验分享·笔记·vue·web
90后的晨仔8 小时前
🚨XSS 攻击全解:什么是跨站脚本攻击?前端如何防御?
前端·vue.js
Ares-Wang8 小时前
JavaScript》》JS》 Var、Let、Const 大总结
开发语言·前端·javascript
90后的晨仔8 小时前
Vue 模板语法完全指南:从插值表达式到动态指令,彻底搞懂 Vue 模板语言
前端·vue.js
德育处主任8 小时前
p5.js 正方形square的基础用法
前端·数据可视化·canvas