当前位置: 首页 > news >正文

基于HTML的Word风格编辑器实现:从零打造功能完备的富文本编辑器

引言

在Web开发中,实现一个功能完备的富文本编辑器是一个常见需求。本文将基于HTML5和JavaScript,结合第三方库,打造一个具有Word风格界面的富文本编辑器,支持格式设置、图片插入、表格创建、文件导入导出等核心功能。
在这里插入图片描述

完整代码解析

以下是完整的HTML5富文本编辑器实现代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Word 编辑器</title><script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.0/mammoth.browser.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script><style>body {font-family: Arial, sans-serif;margin: 0;padding: 20px;background-color: #f5f5f5;}.container {max-width: 1200px;margin: 0 auto;background-color: white;border-radius: 8px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);padding: 20px;}.toolbar {display: flex;flex-wrap: wrap;gap: 5px;margin-bottom: 15px;padding-bottom: 15px;border-bottom: 1px solid #eee;}button, select, input {padding: 8px 12px;border: 1px solid #ddd;border-radius: 4px;background-color: white;cursor: pointer;}button:hover {background-color: #f0f0f0;}.editor {min-height: 500px;border: 1px solid #ddd;padding: 20px;border-radius: 4px;outline: none;}.file-input {display: none;}.status-bar {margin-top: 15px;padding-top: 10px;border-top: 1px solid #eee;color: #666;font-size: 14px;}.active {background-color: #e0e0e0;}.color-picker {width: 30px;height: 30px;padding: 0;border: 1px solid #ddd;}</style>
</head>
<body><div class="container"><h1>Word 编辑器</h1><div class="toolbar"><button id="bold-btn" title="加粗"><b>B</b></button><button id="italic-btn" title="斜体"><i>I</i></button><button id="underline-btn" title="下划线"><u>U</u></button><select id="heading-select"><option value="paragraph">正文</option><option value="h1">标题1</option><option value="h2">标题2</option><option value="h3">标题3</option></select><select id="font-family"><option value="Arial">Arial</option><option value="Times New Roman">Times New Roman</option><option value="Courier New">Courier New</option><option value="宋体">宋体</option><option value="黑体">黑体</option><option value="微软雅黑">微软雅黑</option></select><select id="font-size"><option value="1">8pt</option><option value="2">10pt</option><option value="3">12pt</option><option value="4">14pt</option><option value="5">18pt</option><option value="6">24pt</option><option value="7">36pt</option></select><input type="color" id="text-color" class="color-picker" value="#000000" title="文字颜色"><input type="color" id="bg-color" class="color-picker" value="#FFFFFF" title="背景颜色"><button id="align-left" title="左对齐">左对齐</button><button id="align-center" title="居中对齐">居中</button><button id="align-right" title="右对齐">右对齐</button><button id="insert-list" title="插入列表">列表</button><button id="insert-image" title="插入图片">图片</button><button id="insert-link" title="插入链接">链接</button><button id="insert-table" title="插入表格">表格</button><button id="undo-btn" title="撤销">撤销</button><button id="redo-btn" title="重做">重做</button><button id="import-word" title="导入Word">导入Word</button><button id="export-word" title="导出Word">导出Word</button><button id="export-html" title="导出HTML">导出HTML</button><input type="file" id="file-input" class="file-input" accept=".docx"><input type="file" id="image-input" class="file-input" accept="image/*" style="display: none;"></div><div id="editor" class="editor" contenteditable="true"></div><div class="status-bar"><span id="char-count">0</span> 字符 | <span id="word-count">0</span> 单词 | 光标位置: <span id="cursor-position">0:0</span></div></div><script>document.addEventListener('DOMContentLoaded', function() {const editor = document.getElementById('editor');const boldBtn = document.getElementById('bold-btn');const italicBtn = document.getElementById('italic-btn');const underlineBtn = document.getElementById('underline-btn');const headingSelect = document.getElementById('heading-select');const fontFamily = document.getElementById('font-family');const fontSize = document.getElementById('font-size');const textColor = document.getElementById('text-color');const bgColor = document.getElementById('bg-color');const alignLeft = document.getElementById('align-left');const alignCenter = document.getElementById('align-center');const alignRight = document.getElementById('align-right');const insertList = document.getElementById('insert-list');const insertImage = document.getElementById('insert-image');const insertLink = document.getElementById('insert-link');const insertTable = document.getElementById('insert-table');const undoBtn = document.getElementById('undo-btn');const redoBtn = document.getElementById('redo-btn');const importWord = document.getElementById('import-word');const exportWord = document.getElementById('export-word');const exportHtml = document.getElementById('export-html');const fileInput = document.getElementById('file-input');const imageInput = document.getElementById('image-input');const charCount = document.getElementById('char-count');const wordCount = document.getElementById('word-count');const cursorPosition = document.getElementById('cursor-position');// 初始化编辑器内容editor.innerHTML = '<p>开始编辑您的文档...</p>';// 更新字数统计和光标位置function updateCount() {const text = editor.innerText;charCount.textContent = text.length;wordCount.textContent = text.trim() === '' ? 0 : text.trim().split(/\s+/).length;// 更新光标位置const selection = window.getSelection();if (selection.rangeCount > 0) {const range = selection.getRangeAt(0);const preCaretRange = range.cloneRange();preCaretRange.selectNodeContents(editor);preCaretRange.setEnd(range.endContainer, range.endOffset);const line = preCaretRange.toString().split('\n').length;const column = range.endOffset;cursorPosition.textContent = `${line}:${column}`;}}editor.addEventListener('input', updateCount);editor.addEventListener('click', updateCount);editor.addEventListener('keyup', updateCount);updateCount();// 加粗boldBtn.addEventListener('click', function() {document.execCommand('bold', false, null);this.classList.toggle('active');});// 斜体italicBtn.addEventListener('click', function() {document.execCommand('italic', false, null);this.classList.toggle('active');});// 下划线underlineBtn.addEventListener('click', function() {document.execCommand('underline', false, null);this.classList.toggle('active');});// 标题样式headingSelect.addEventListener('change', function() {const value = this.value;if (value === 'paragraph') {document.execCommand('formatBlock', false, '<p>');} else {document.execCommand('formatBlock', false, `<${value}>`);}});// 字体fontFamily.addEventListener('change', function() {document.execCommand('fontName', false, this.value);});// 字号fontSize.addEventListener('change', function() {document.execCommand('fontSize', false, this.value);});// 文字颜色textColor.addEventListener('input', function() {document.execCommand('foreColor', false, this.value);});// 背景颜色bgColor.addEventListener('input', function() {document.execCommand('hiliteColor', false, this.value);});// 对齐方式alignLeft.addEventListener('click', function() {document.execCommand('justifyLeft', false, null);alignLeft.classList.add('active');alignCenter.classList.remove('active');alignRight.classList.remove('active');});alignCenter.addEventListener('click', function() {document.execCommand('justifyCenter', false, null);alignLeft.classList.remove('active');alignCenter.classList.add('active');alignRight.classList.remove('active');});alignRight.addEventListener('click', function() {document.execCommand('justifyRight', false, null);alignLeft.classList.remove('active');alignCenter.classList.remove('active');alignRight.classList.add('active');});// 插入列表insertList.addEventListener('click', function() {document.execCommand('insertUnorderedList', false, null);});// 插入图片insertImage.addEventListener('click', function() {const option = prompt('输入图片URL或选择"上传"从本地上传图片', '');if (option === '上传') {imageInput.click();} else if (option && option !== '') {document.execCommand('insertImage', false, option);}});imageInput.addEventListener('change', function(e) {const file = e.target.files[0];if (!file) return;const reader = new FileReader();reader.onload = function(event) {document.execCommand('insertImage', false, event.target.result);};reader.readAsDataURL(file);this.value = ''; // 重置input,以便可以重复选择同一文件});// 插入链接insertLink.addEventListener('click', function() {const url = prompt('请输入链接URL:');if (url) {const text = window.getSelection().toString() || '链接';document.execCommand('insertHTML', false, `<a href="${url}" target="_blank">${text}</a>`);}});// 插入表格insertTable.addEventListener('click', function() {const rows = prompt('输入行数:', '3');const cols = prompt('输入列数:', '3');if (rows && cols) {let tableHtml = '<table border="1" style="width:100%; border-collapse:collapse;">';for (let i = 0; i < parseInt(rows); i++) {tableHtml += '<tr>';for (let j = 0; j < parseInt(cols); j++) {tableHtml += '<td style="padding:8px;">内容</td>';}tableHtml += '</tr>';}tableHtml += '</table>';document.execCommand('insertHTML', false, tableHtml);}});// 撤销undoBtn.addEventListener('click', function() {document.execCommand('undo', false, null);updateCount();});// 重做redoBtn.addEventListener('click', function() {document.execCommand('redo', false, null);updateCount();});// 导入WordimportWord.addEventListener('click', function() {fileInput.click();});fileInput.addEventListener('change', function(e) {const file = e.target.files[0];if (!file) return;const reader = new FileReader();reader.onload = function(event) {const arrayBuffer = event.target.result;mammoth.extractRawText({arrayBuffer: arrayBuffer}).then(function(result) {editor.innerHTML = result.value;updateCount();}).catch(function(error) {console.error(error);alert('导入Word文件失败: ' + error.message);});};reader.readAsArrayBuffer(file);});// 导出Word - 使用HTML转DOCX的替代方案exportWord.addEventListener('click', function() {// 创建一个包含HTML内容的Blobconst htmlContent = `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Document</title><style>body { font-family: Arial, sans-serif; margin: 20px; }h1 { color: #000000; }p { margin-bottom: 10px; }</style></head><body>${editor.innerHTML}</body></html>`;// 创建一个包含HTML内容的Blobconst blob = new Blob([htmlContent], { type: 'application/msword' });// 使用FileSaver.js保存文件saveAs(blob, "document.doc");});// 导出HTMLexportHtml.addEventListener('click', function() {const htmlContent = editor.innerHTML;const blob = new Blob([htmlContent], { type: 'text/html' });saveAs(blob, "document.html");});// 检查当前选区样式document.addEventListener('selectionchange', function() {const selection = window.getSelection();if (selection.rangeCount === 0) return;const range = selection.getRangeAt(0);const parentElement = range.commonAncestorContainer.parentElement;// 检查加粗boldBtn.classList.toggle('active', document.queryCommandState('bold'));// 检查斜体italicBtn.classList.toggle('active', document.queryCommandState('italic'));// 检查下划线underlineBtn.classList.toggle('active', document.queryCommandState('underline'));// 检查对齐方式const align = parentElement.style.textAlign || window.getComputedStyle(parentElement).textAlign;alignLeft.classList.remove('active');alignCenter.classList.remove('active');alignRight.classList.remove('active');if (align === 'left') alignLeft.classList.add('active');else if (align === 'center') alignCenter.classList.add('active');else if (align === 'right') alignRight.classList.add('active');// 更新光标位置updateCount();});// 添加键盘快捷键支持document.addEventListener('keydown', function(e) {// Ctrl+B - 加粗if (e.ctrlKey && e.key === 'b') {e.preventDefault();boldBtn.click();}// Ctrl+I - 斜体else if (e.ctrlKey && e.key === 'i') {e.preventDefault();italicBtn.click();}// Ctrl+U - 下划线else if (e.ctrlKey && e.key === 'u') {e.preventDefault();underlineBtn.click();}// Ctrl+Z - 撤销else if (e.ctrlKey && e.key === 'z') {if (!e.shiftKey) {e.preventDefault();undoBtn.click();}}// Ctrl+Y 或 Ctrl+Shift+Z - 重做else if ((e.ctrlKey && e.key === 'y') || (e.ctrlKey && e.shiftKey && e.key === 'z')) {e.preventDefault();redoBtn.click();}});});</script>
</body>
</html>

核心功能实现

1. 编辑器基础结构

编辑器采用经典的contenteditable属性实现可编辑区域:

<div id="editor" class="editor" contenteditable="true"></div>

配合CSS样式:

.editor {min-height: 500px;border: 1px solid #ddd;padding: 20px;border-radius: 4px;outline: none;
}

2. 格式设置功能

使用document.execCommand()实现基础格式设置:

// 加粗
boldBtn.addEventListener('click', function() {document.execCommand('bold', false, null);this.classList.toggle('active');
});// 斜体
italicBtn.addEventListener('click', function() {document.execCommand('italic', false, null);this.classList.toggle('active');
});// 标题样式
headingSelect.addEventListener('change', function() {const value = this.value;if (value === 'paragraph') {document.execCommand('formatBlock', false, '<p>');} else {document.execCommand('formatBlock', false, `<${value}>`);}
});

3. 样式状态同步

通过selectionchange事件监听选区变化,更新按钮状态:

document.addEventListener('selectionchange', function() {// 检查加粗状态boldBtn.classList.toggle('active', document.queryCommandState('bold'));// 检查斜体状态italicBtn.classList.toggle('active', document.queryCommandState('italic'));// 检查对齐方式const selection = window.getSelection();if (selection.rangeCount > 0) {const range = selection.getRangeAt(0);const parentElement = range.commonAncestorContainer.parentElement;const align = parentElement.style.textAlign || window.getComputedStyle(parentElement).textAlign;alignLeft.classList.remove('active');alignCenter.classList.remove('active');alignRight.classList.remove('active');if (align === 'left') alignLeft.classList.add('active');else if (align === 'center') alignCenter.classList.add('active');else if (align === 'right') alignRight.classList.add('active');}
});

4. 图片插入功能

支持URL输入和本地文件上传两种方式:

insertImage.addEventListener('click', function() {const option = prompt('输入图片URL或选择"上传"从本地上传图片', '');if (option === '上传') {imageInput.click(); // 触发隐藏的文件输入} else if (option && option !== '') {document.execCommand('insertImage', false, option);}
});// 本地文件上传处理
imageInput.addEventListener('change', function(e) {const file = e.target.files[0];if (!file) return;const reader = new FileReader();reader.onload = function(event) {document.execCommand('insertImage', false, event.target.result);};reader.readAsDataURL(file);this.value = ''; // 重置input
});

5. 表格插入功能

通过对话框获取行列数,动态生成HTML表格:

insertTable.addEventListener('click', function() {const rows = prompt('输入行数:', '3');const cols = prompt('输入列数:', '3');if (rows && cols) {let tableHtml = '<table border="1" style="width:100%; border-collapse:collapse;">';for (let i = 0; i < parseInt(rows); i++) {tableHtml += '<tr>';for (let j = 0; j < parseInt(cols); j++) {tableHtml += '<td style="padding:8px;">内容</td>';}tableHtml += '</tr>';}tableHtml += '</table>';document.execCommand('insertHTML', false, tableHtml);}
});

6. 文件导入导出

导入Word文档

fileInput.addEventListener('change', function(e) {const file = e.target.files[0];if (!file) return;const reader = new FileReader();reader.onload = function(event) {const arrayBuffer = event.target.result;mammoth.extractRawText({arrayBuffer: arrayBuffer}).then(function(result) {editor.innerHTML = result.value;updateCount();}).catch(function(error) {console.error(error);alert('导入Word文件失败: ' + error.message);});};reader.readAsArrayBuffer(file);
});

导出Word文档

exportWord.addEventListener('click', function() {const htmlContent = `<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Document</title><style>body { font-family: Arial, sans-serif; margin: 20px; }h1 { color: #000000; }p { margin-bottom: 10px; }</style></head><body>${editor.innerHTML}</body></html>`;const blob = new Blob([htmlContent], { type: 'application/msword' });saveAs(blob, "document.doc");
});

高级功能实现

1. 键盘快捷键支持

document.addEventListener('keydown', function(e) {// Ctrl+B - 加粗if (e.ctrlKey && e.key === 'b') {e.preventDefault();boldBtn.click();}// Ctrl+I - 斜体else if (e.ctrlKey && e.key === 'i') {e.preventDefault();italicBtn.click();}// Ctrl+U - 下划线else if (e.ctrlKey && e.key === 'u') {e.preventDefault();underlineBtn.click();}// Ctrl+Z - 撤销else if (e.ctrlKey && e.key === 'z') {if (!e.shiftKey) {e.preventDefault();undoBtn.click();}}// Ctrl+Y 或 Ctrl+Shift+Z - 重做else if ((e.ctrlKey && e.key === 'y') || (e.ctrlKey && e.shiftKey && e.key === 'z')) {e.preventDefault();redoBtn.click();}
});

2. 字数统计功能

function updateCount() {const text = editor.innerText;charCount.textContent = text.length;wordCount.textContent = text.trim() === '' ? 0 : text.trim().split(/\s+/).length;// 更新光标位置const selection = window.getSelection();if (selection.rangeCount > 0) {const range = selection.getRangeAt(0);const preCaretRange = range.cloneRange();preCaretRange.selectNodeContents(editor);preCaretRange.setEnd(range.endContainer, range.endOffset);const line = preCaretRange.toString().split('\n').length;const column = range.endOffset;cursorPosition.textContent = `${line}:${column}`;}
}

第三方库使用

  1. Mammoth.js:用于将Word文档(.docx)转换为HTML

    <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.4.0/mammoth.browser.min.js"></script>
    
  2. FileSaver.js:用于文件保存功能

    <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
    

改进建议

  1. 样式保留:当前导入Word时只保留了纯文本,建议使用Mammoth的完整转换功能

    mammoth.convertToHtml({arrayBuffer: arrayBuffer}).then(function(result) {editor.innerHTML = result.value;updateCount();})
    
  2. 撤销重做系统document.execCommand的撤销重做功能有限,建议实现自定义的历史记录栈

  3. 响应式设计:在小屏幕设备上优化工具栏布局

  4. 协作编辑:添加WebSocket支持实现多人协作

总结

本文实现了一个功能完备的富文本编辑器,具有以下特点:

  1. 完整的Word风格界面
  2. 多种格式设置功能
  3. 图片和表格插入
  4. 文件导入导出
  5. 键盘快捷键支持
  6. 字数统计和光标位置显示

这个编辑器可以作为基础框架,根据实际需求进行扩展,如添加Markdown支持、PDF导出、模板功能等。对于生产环境使用,建议考虑使用成熟的编辑器库如Quill、TinyMCE或CKEditor,但理解底层实现原理对于深入掌握前端开发至关重要。

相关文章:

基于HTML的Word风格编辑器实现:从零打造功能完备的富文本编辑器

引言 在Web开发中&#xff0c;实现一个功能完备的富文本编辑器是一个常见需求。本文将基于HTML5和JavaScript&#xff0c;结合第三方库&#xff0c;打造一个具有Word风格界面的富文本编辑器&#xff0c;支持格式设置、图片插入、表格创建、文件导入导出等核心功能。 完整代码…...

亚远景-汽车软件开发的“升级之路”:ASPICE各等级说明

ASPICE&#xff08;Automotive SPICE&#xff09;将汽车软件开发过程的成熟度划分为六个等级&#xff0c;从0级到5级&#xff0c;每个等级代表了组织在软件开发过程中的不同能力水平。以下是各等级的详细说明&#xff1a; 等级0&#xff1a;不完整&#xff08;Incomplete&#…...

Unity Display 1 No cameras rendering

一个相机不能同时输出到屏幕和RenderTexture​​。 Output Texture&#xff0c;要么是 None &#xff08;屏幕&#xff09;&#xff0c;要么是RenderTexture。 如果此时相机已经输出到RenderTexture&#xff0c;场景中又没有别的相机在渲染&#xff0c;屏幕将变黑并显示No cam…...

Python Selenium 使用指南

Selenium 是一个用于自动化 Web 浏览器交互的强大工具&#xff0c;常用于网页测试、数据抓取和自动化任务。以下是 Python 中 Selenium 的详细使用说明。 安装 Selenium 首先需要安装 Selenium 库和浏览器驱动&#xff1a; pip install selenium 然后下载对应浏览器的驱动&…...

Cribl 对数据源进行过滤-01

先说一个项目中实际的例子: Cribl 利用filter expression 来过滤 data, 举个例子: source1: sourcerouter=A, source 2: sourcerouter=B, 这个时候,可以要把他们合并起来: sourcerouter=A || sourcerouter=B 来进行过滤想要的数据。 最后可以使用一个pipeline 来对数据进行…...

python 通过 pymysql 获取 select count(*) xxx 的数量

在使用 pymysql 库来获取 SELECT COUNT(*) 语句的结果时&#xff0c;你可以通过以下步骤实现&#xff1a; 安装 pymysql&#xff1a;如果你还没有安装 pymysql&#xff0c;可以通过 pip 安装它。 pip install pymysql连接到数据库&#xff1a;使用 pymysql.connect() 方法连接…...

定时任务延迟任务

二者的区别&#xff1a; 定时任务&#xff1a;有固定周期的&#xff0c;有明确的触发时间。 延迟任务&#xff1a;没有固定的开始时间&#xff0c;它常常是由一个事件触发的&#xff0c;而在这个事件触发之后的一段时间内触发另一个事件&#xff0c;任务可以立即执行&#xff0…...

【动手学深度学习】1.1~1.2 机器学习及其关键组件

目录 一、引言1.1. 日常生活中的机器学习1.2. 机器学习中的关键组件1&#xff09;数据2&#xff09;模型3&#xff09;目标函数4&#xff09;优化算法 一、引言 1.1. 日常生活中的机器学习 应用场景&#xff1a; 以智能语音助手&#xff08;如Siri、Alexa&#xff09;的唤醒…...

LLaVA-MoD:基于MoE结构和蒸馏训练方法,训练轻量化多模态大模型!!

摘要&#xff1a;我们介绍了LLaVA-MoD&#xff0c;这是一个旨在高效训练小型多模态语言模型&#xff08;s-MLLM&#xff09;的创新框架&#xff0c;通过从大规模多模态语言模型&#xff08;l-MLLM&#xff09;中提取知识来实现。我们的方法解决了多模态语言模型&#xff08;MLL…...

YOLOv8 的双 Backbone 架构:解锁目标检测新性能

一、开篇&#xff1a;为何踏上双 Backbone 探索之路 在目标检测的领域中&#xff0c;YOLOv8 凭借其高效与精准脱颖而出&#xff0c;成为众多开发者和研究者的得力工具。然而&#xff0c;传统的单 Backbone 架构&#xff0c;尽管已经在诸多场景中表现出色&#xff0c;但仍存在一…...

SSRF(服务器端请求伪造)基本原理靶场实现

1、漏洞原理 攻击者通过构造恶意请求&#xff0c;诱使服务器向内部系统或第三方服务发起非预期的网络请求。其核心在于 服务器信任了不可信的用户输入&#xff0c;并基于该输入发起网络操作。 2、攻击场景与利用方式 1. 基础利用 攻击类型示例Payload目标读取本地文件file://…...

自动化测试脚本点击运行后,打开Chrome很久??

亲爱的小伙伴们大家好。 小编最近刚换了电脑&#xff0c;这几天做自动化测试发现打开Chrome浏览器需要等待好长时间&#xff0c;起初还以为代码有问题&#xff0c;或者Chromedriver与Chrome不匹配造成的&#xff0c;但排查后发现并不是&#xff01;&#xff01; 在driver.py中…...

Oracle中如何解决FREE BUFFER WAITS

基于性能上的考虑&#xff0c;服务器进程在扫描LRU主列的同时&#xff0c;会将脏块移至LRU-W列&#xff0c;如果发现没有足够可用&#xff08;可替换&#xff09;的BUFFER CACHE&#xff0c;进程并不会无止尽地扫描整条LRU主列&#xff0c;而是在扫描到某个阀值&#xff08;该阀…...

OpenHarmony开源鸿蒙兼容性测试常见问题解答分享

OpenHarmony 兼容性测评主要是验证合作伙伴的设备和业务应用满足 OpenHarmony 开源兼容性定义的技术要求&#xff0c;确保运行在 OpenHarmony 上的设备和业务应用能稳定、正常运行&#xff0c;同时使用 OpenHarmony 的设备和业务应用有一致性的接口和业务体验。 一、兼容性测评…...

Android trace presentFence屏幕显示的帧

Android trace presentFence屏幕显示的帧 presentFence &#xff1a;当帧成功显示到屏幕时&#xff0c;present fence就会signal。 FrameMissed/GpuFrameMissed/HwcFrameMissed表示上一次合成的结果&#xff0c;当SurfaceFlinger合成后显示到屏幕上&#xff0c;present fence就…...

【520特辑】情人节脑影像绘图

祝大家520快乐&#xff01; 永远爱自己&#xff01; 1.Brain Net基于节点画爱心 clear all; clc;t linspace(0, 2*pi, 30); x 16*sin(t).^3; y 13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t); z zeros(size(t));[X,Y] meshgrid(linspace(-10,10,5), linspace(-10,10,5)); X …...

Linux服务器配置深度学习环境(Pytorch+Anaconda极简版)

前言&#xff1a; 最近做横向需要使用实验室服务器跑模型&#xff0c;之前用师兄的账号登录服务器跑yolo&#xff0c;3张3090一轮14秒&#xff0c;我本地一张4080laptop要40秒&#xff0c;效率还是快很多&#xff0c;&#xff08;这么算一张4080桌面版居然算力能比肩3090&#…...

如何理解大模型的幻觉输出及RAG技术的应用与实战案例

导读&#xff1a;大语言模型&#xff08;LLM&#xff09;在当今技术领域中扮演着越来越重要的角色&#xff0c;但其“幻觉输出”问题却成为实际应用中的痛点。本文将带你深入剖析这一现象的定义、表现形式及成因&#xff0c;并探讨如何通过RAG&#xff08;检索增强生成&#xf…...

std::vector<>.emplace_back

emplace_back() 详解&#xff1a;C 就地构造的效率革命 emplace_back() 是 C11 引入的容器成员函数&#xff0c;用于在容器尾部就地构造&#xff08;而非拷贝或移动&#xff09;元素。这一特性显著提升了复杂对象的插入效率&#xff0c;尤其适用于构造代价较高的类型。 一、核…...

卷积神经网络(CNN)学习率调整完全指南:从理论到PyTorch实践

引言 学习率是训练卷积神经网络(CNN)最重要的超参数之一&#xff0c;合理调整学习率可以显著提高模型性能、加速收敛并避免训练失败。本文将全面解析CNN学习率调整的技术与方法&#xff0c;涵盖基础概念、常用策略、PyTorch实现以及实用技巧。 一、学习率为什么如此重要&…...

KLEC--基于知识学习的演化计算算法

KLEC–基于知识学习的演化计算算法 title&#xff1a; Knowledge Learning for Evolutionary Computation author&#xff1a; Yi Jiang, Zhi-Hui Zhan, Kay Chen Tan, Jun Zhang. journal&#xff1a; IEEE TRANSACTIONS ON EVOLUTIONARY COMPUTATION (TEVC) DOI&#xff…...

Git查看指定作者提交命令

要查看 Git 仓库中某个作者的提交记录&#xff0c;可以使用 git log 命令结合 --author 选项。以下是具体用法和示例&#xff1a; 基础命令 git log --author"作者名"作用&#xff1a;列出指定作者的所有提交记录。示例&#xff1a;查找作者名为 John Doe 的提交&am…...

隐形安全感

凌晨两点&#xff0c;手机突然震动。合作三年的化工原料供应商发来紧急消息&#xff1a;“一批次环氧树脂需要连夜从南京调往广州&#xff0c;但合作多年的物流公司临时爽约&#xff0c;能帮忙想想办法吗&#xff1f;” 我盯着屏幕愣了几秒。这类危险品运输从来不是简单的“拉…...

代码随想录算法训练营 Day52 图论Ⅲ 岛屿问题Ⅱ 面积 孤岛 水流 造岛

图论 题目 101. 孤岛的总面积 计算孤岛总面积&#xff0c;一个想法是将相邻的陆地的位置置为 0&#xff0c;最后计算孤岛面积中最小的一个 #include <iostream> #include <vector> #include <queue>using namespace std;int sum 0; int dir[4][2] {0,-1…...

实用 Git 学习工具推荐:Learn Git Branching

https://learngitbranching.js.org/?localezh_CN 网站概述 Learn Git Branching 是一个面向开发者的交互式 Git 学习平台&#xff0c;专为那些希望通过实践掌握 Git 高级用法的用户设计。网站采用游戏化的界面和渐进式挑战&#xff0c;让复杂的 Git 概念变得直观易懂。无论是…...

物流项目第三期(统一网关、工厂模式运用)

前两期&#xff1a; 物流项目第一期&#xff08;登录业务&#xff09;-CSDN博客 物流项目第二期&#xff08;用户端登录与双token三验证&#xff09;-CSDN博客 为什么要有网关&#xff1f; 通过前面的课程我们已经完成了四个端的登录&#xff0c;但是我们并没有对登录后的请…...

安卓settings单双屏显示

Settings/src/com/android/settings/homepage/SettingsHomepageActivity.java的onCreate方法中&#xff0c;创建布局之前会通过ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this);去获取是否使用嵌入式显示。 mIsEmbeddingActivityEnabled ActivityEmbeddingUtils.is…...

SpringCloud+Vue实现大文件分片下载(支持开始、暂停、继续、取消)

1. 实现效果 http://localhost:8089/#/demo 所有代码已提交至 https://github.com/SJshenjian/cloud.git与 https://github.com/SJshenjian/cloud-web.git中&#xff0c;欢迎star 2. 后端核心代码 FeignClient(value "download", contextId "download"…...

RK3576 Android 14.0 SDK开发指南(第一集)

RK3576 Android 14.0 SDK代码编译 SDK下载到本地后大概70多个G 下载后要做个校验 解压后内核源码 kernel代码路径说明 Android14支持6.1 版本的kernel&#xff0c;kernel源码在工程中kernel-6.1目录下 Lunch项说明 一键编译命令 ./build.sh -UKAupSoc RK3576 SDK默认没有开…...

【C/C++】现代C++线程池:从入门到生产级实现

文章目录 现代C线程池&#xff1a;从入门到生产级实现&#x1f9e0; What Is a Thread Pool?&#x1f9e9; Why Use a Thread Pool?&#x1f530; Part 1: Basic Thread Pool (Beginner)&#x1f527; Minimal Working Code:✅ Usage: &#x1f9d1;‍&#x1f52c; Part 2: …...

后期:daplink

问题描述: 问题一:总工程,USB插入能识别到dap,但有个黄色的感叹号!现在连感叹号都没有了。 重点跟踪了枚举的几个函数,差异点就是有个工厂描述符没有枚举到。 问题二: 下载后,目标板,没有自动复位。 问题三:未移植daplink的时候,虚拟串口是收发正常,貌似没有映射到…...

Android SharedPreferences:从零到一的全面解析与实战指南

简介 SharedPreferences是Android平台提供的一种轻量级键值对存储方案,虽然看似简单,但在实际开发中却蕴含着丰富的技术细节和最佳实践。本文将从基本概念出发,深入分析其源码实现原理,探讨企业级开发中的应用技巧,并提供完整的代码示例,帮助开发者全面掌握这一重要数据…...

推扫式高光谱相机VIX-N230重磅发布——开启精准成像新时代

随着各行业对高光谱成像技术需求的持续增长&#xff0c;市场对于高分辨率、高灵敏度以及快速成像的高光谱相机的需求愈发迫切。中达瑞和凭借多年的行业经验和技术积累&#xff0c;敏锐捕捉到这一市场趋势&#xff0c;正式推出全新一代推扫式可见光近红外高光谱相机——VIX-N230…...

实现rpc通信机制(待定)

一、概述 &#xff08;1&#xff09;rpc&#xff08;remote procedure call, 远程接口调用&#xff09;,就像在本地调用函数一样&#xff0c;是应用组成服务内部分布式的基础功能。应用场景是在内网中的计算&#xff0c;比如&#xff1a;(a) 为上传的一张图片加水印、&#xf…...

STM32--串口函数

USART_GetFlagStatus() 用于获取某个串口的寄存器中的某个标志位的状态&#xff0c;和中断无关。 USART_ClearFlag() 用于清楚串口寄存器中的标志位的状态&#xff0c;和中断无关。 USART_ITConfig() 使能或禁用指定的 USART 中断。 USART_ITConfig(USART1, USART_IT_TXE, …...

Linux跨网络通信中IP与MAC的作用

是的&#xff0c;MAC地址和IP地址分别属于OSI模型的不同层次&#xff0c;并在数据封装过程中被添加到不同的位置&#xff1a; 1. MAC地址&#xff08;数据链路层&#xff09; 作用层级&#xff1a;数据链路层&#xff08;第二层&#xff09;。封装位置&#xff1a;添加到数据链…...

Facebook隐私保护的成与败:一场对用户信任的考验

引言 在这个信息爆炸的时代&#xff0c;Facebook作为全球最大的社交网络平台之一&#xff0c;其隐私保护政策和实践一直是公众关注的焦点。随着数据泄露事件的频发&#xff0c;Facebook在隐私保护方面的成与败&#xff0c;不仅关系到其自身的声誉&#xff0c;更是对用户信任的…...

面试算法刷题3(核心+acm)

102. 二叉树的层序遍历 递归法 核心代码模式 不断递归根节点&#xff0c;根据深度来判断加在哪一层上。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(in…...

[Java] idea的调试介绍

1. 什么是调试&#xff1f; 调试就是帮助我们去寻找代码中的bug&#xff0c;优化代码的过程。调试对于程序员来说非常重要&#xff0c;能帮助我们更容易去找到代码中的错误&#xff0c;去修复。 2. idea集成开发环境的调试 下面我就介绍下idea集成开发环境下的调试&#xff…...

winrm ‘Protocol‘ object has no attribute ‘run_ps‘

在使用 winrm 库时遇到错误 ‘Protocol’ object has no attribute ‘run_ps’ 通常意味着你正在尝试使用一个不存在的属性或方法。在 Python 中使用 winrm 库时&#xff0c;正确的调用方式应该使用 client 对象来运行 PowerShell 命令&#xff0c;而不是直接在 Protocol 对象上…...

WHAT - CSS 中的 min-width

文章目录 基本语法常见取值使用场景举例min-width: 0为什么 min-width: 0 重要&#xff1f;场景演示提示 注意事项 在 WHAT - CSS 中的 width 中我们已经详细介绍过 width。那为什么 CSS 还要提供一个 min-width&#xff1f; 阅读本文前可先阅读 MDN - min-width。 min-width…...

测试W5500的第2步_使用ioLibrary库创建TCP客户端

ioLibrary库下载地址&#xff1a;文件下载地址:https://gitee.com/wiznet-hk/STM32F10x_W5500_Examples 源文件下载地址:https://gitee.com/wiznet-hk 没有注册的&#xff0c;只能复制粘贴了。 本文介绍了如何初始化STM32的硬件资源&#xff0c;配置W5500的网络参数&#xff…...

深度学习中的正则化方法与卷积神经网络基础

笔记 1 正则化方法 1.1 什么是正则化 防止模型过拟合(训练集效果好, 测试集效果差), 提高模型泛化能力 一种防止过拟合, 提高模型泛化能力的策略 L1正则: 需要通过手动写代码实现 L2正则: SGD(weight_decay) dropout BN 1.2 Dropout正则化 让神经元以p概率随机死亡, 每…...

pg_dump

以下是 PostgreSQL 中 pg_dump 命令的 核心参数 及 使用示例 的详细说明&#xff1a; 一、核心参数分类及说明 pg_dump 主要用于备份单个数据库&#xff0c;支持多种格式和灵活的控制选项。以下是其关键参数分类&#xff1a; 1. 连接参数 参数说明-h, --hostHOST数据库服务器…...

css使用clip-path属性切割显示可见内容

1. 需求 想要实现一个渐变的箭头Dom&#xff0c;不想使用svg、canvas去画&#xff0c;可以考虑使用css的clip-path属性切割显示内容。 2. 实现 <div class"arrow">箭头 </div>.arrow{width: 200px;height: 60px;background-image: linear-gradient(45…...

系统设计——项目设计经验总结1

摘要 在系统设计的时候&#xff0c;注意域的区分&#xff0c;功能区分、类的区分、方法区分范围和定义。在系统设计的时候的&#xff0c;需要思考类、方法在什么情况下会涉及到修改&#xff0c;遵循记住&#xff1a;一个类应该只有一个原因被修改&#xff01; 当不满足&#x…...

如何在WordPress网站上添加即时聊天功能

在 WordPress 网站上添加即时聊天功能既简单又有益。近年来&#xff0c;即时聊天已经有了长足的发展&#xff0c;融入了强大的交流和自动化功能&#xff0c;类似于流行的人工智能聊天机器人。无论您是想提高销售转化率还是将人工智能整合到客户服务流程中&#xff0c;在 WordPr…...

[luogu12542] [APIO2025] 排列游戏 - 交互 - 博弈 - 分类讨论 - 构造

传送门&#xff1a;https://www.luogu.com.cn/problem/P12542 题目大意&#xff1a;给定一个长为 n n n 的排列和一张 m m m 个点 e e e 条边的简单连通图。每次你可以在图上每个点设置一个 0 ∼ n − 1 0\sim n-1 0∼n−1、两两不同的权值发给交互库&#xff0c;交互库会…...

图像处理基础知识

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 信息是自然界物质运动总体的一个重要方面&#xff0c;人们认识世界和改造世界就是要获得各种各样的图像信息&#xff0c;这些信息是人类获得外界信息的主要来源。大约有70%的信息是通过人眼获得的。近代科学研…...

使用MybatisPlus实现sql日志打印优化

背景&#xff1a; 在排查无忧行后台服务日志时&#xff0c;一个请求可能会包含多个执行的sql&#xff0c;经常会遇到SQL语句与对应参数不连续显示&#xff0c;或者参数较多需要逐个匹配的情况。这种情况下&#xff0c;如果需要还原完整SQL语句就会比较耗时。因此&#xff0c;我…...