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

Javascript网页设计案例:通过PDF.js实现一款PDF阅读器,包括预览、页面旋转、页面切换、放大缩小、黑夜模式等功能

前言

目前功能包括:

  • 切换到首页。
  • 切换到尾页。
  • 上一页。
  • 下一页。
  • 添加标签。
  • 标签管理
  • 页面旋转
  • 页面随意拖动
  • 双击后还原位置

其实按照自己的预期来说,有很多功能还没有开发完,配色也没有全都搞完,先发出来吧,后期有需要继续添加功能。

功能预览

1.加载后的主页面

白天模式
在这里插入图片描述
黑夜模式
在这里插入图片描述

2.功能区

在这里插入图片描述

一、关于这款PDF阅读器的功能说明

1. 基本布局与样式

  • 具有响应式设计,通过meta标签设置视口以适应不同设备宽度。
  • 支持主题切换(明暗模式),定义了一系列CSS变量来管理颜色和布局相关属性,方便切换不同主题风格。

2. 工具栏功能

  • 导航功能:包含首页、上一页、下一页、末页的导航按钮,对应firstPage()prevPage()nextPage()lastPage()函数。
  • 缩放功能:有缩小、放大按钮,分别对应zoomOut()zoomIn()函数,还提供了一个范围输入控件#zoomControl用于更精确地控制缩放比例。
  • 旋转功能:顺时针旋转和逆时针旋转按钮,对应rotateClockwise()rotateCounterClockwise()函数。
  • 书签功能:可以输入书签名称,点击添加书签按钮(addBookmark()函数)添加书签,还有书签管理按钮(toggleBookmarkPanel()函数)用于管理已添加的书签。
  • 主题切换:有一个主题切换按钮(toggleTheme()函数),点击可切换明暗主题。

3. 侧边栏与缩略图

  • 侧边栏(.sidebar)用于显示PDF文档的缩略图,缩略图容器为#thumbnails,每个缩略图项(.thumbnail-item)包含一个canvas元素用于显示缩略图,点击缩略图项可进行相关操作。

4. 主内容区域

  • 主内容区域(.main-content)包含PDF文档的显示区域(#pdf-container),其中有一个canvas元素(#pdf-canvas)用于渲染PDF页面,用户可以通过鼠标抓取操作(cursor: -webkit-grab)进行交互。
  • 状态栏(.status-bar)用于显示一些状态信息,如页码等。

5. 模态窗口

  • 书签管理模态窗口(#bookmarks-modal),默认隐藏,用于管理已添加的书签,包含书签列表(#bookmarks-list)和一些操作按钮(.modal-buttons)。

二、Html代码

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><title>PDF阅读器</title><style>:root {--primary-color: #2196F3;--hover-color: #1976D2;--background-color: #1a1a1a;--surface-color: #2d2d2d;--toolbar-bg: #333333;--text-color: #ffffff;--error-color: #ff4444;--border-radius: 8px;--gap: 20px;--toolbar-height: 60px;}body {font-family: Arial, sans-serif;margin: 0;padding: 20px;background-color: var(--background-color);color: var(--text-color);box-sizing: border-box;}.pdf-reader-container {display: flex;gap: var(--gap);max-width: 100%;min-width: 800px;margin: 0 auto;background-color: var(--surface-color);border-radius: var(--border-radius);box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);padding: var(--gap) ; /* 0 上下内边距 */margin-top: var(--toolbar-height);box-sizing: border-box;flex-wrap: nowrap;}.toolbar {position: fixed;top: 0;left: 0;right: 0;height: var(--toolbar-height);display: flex;align-items: center;justify-content: space-between;padding: 0 var(--gap);background-color: var(--toolbar-bg);border-radius: 0 0 var(--border-radius) var(--border-radius);box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);z-index: 1000;box-sizing: border-box;}.logo {display: flex;align-items: center;padding: 0 20px;height: 60%;}.logo img {height: 100%;object-fit: contain; transition: transform 0.3s ease; }.toolbar-buttons {display: flex;gap: 10px;}/* 修改按钮样式部分 */button {padding: 8px 12px;font-size: 16px;cursor: pointer;background-color: var(--primary-color);color: var(--text-color);border: none;border-radius: 50%;aspect-ratio: 1/1;transition: all 0.3s ease;display: flex;align-items: center;justify-content: center;width: 40px;height: 40px;position: relative;}button:hover {background-color: var(--hover-color);transform: translateY(-2px);box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}button::before {font-family: "Font Awesome 5 Free";font-weight: 900;}/* 为每个按钮指定图标 */button:nth-child(1)::before { content: "\f100"; } /* 首页 */button:nth-child(2)::before { content: "\f104"; } /* 上一页 */button:nth-child(3)::before { content: "\f105"; } /* 下一页 */button:nth-child(4)::before { content: "\f101"; } /* 末页 */button:nth-child(5)::before { content: "\f068"; } /* 缩小 */button:nth-child(7)::before { content: "\f067"; } /* 放大 */button:nth-child(8)::before { content: "\f2f9"; } /* 顺时针旋转 */button:nth-child(9)::before { content: "\f2ea"; } /* 逆时针旋转 */button:nth-child(11)::before { content: "\f02e"; } /* 添加书签 */button:nth-child(12)::before { content: "\f02e"; } /* 书签管理 */button span {display: none;}.toolbar-buttons {display: flex;gap: 8px;align-items: center;}#zoomControl {width: 100px;height: 6px;background: var(--surface-color);border-radius: 3px;}#bookmarkLabel {padding: 8px;border-radius: var(--border-radius);border: 1px solid var(--primary-color);background: var(--surface-color);color: var(--text-color);}button::after {content: attr(aria-label);position: absolute;bottom: -30px;left: 50%;transform: translateX(-50%);background: var(--toolbar-bg);color: var(--text-color);padding: 4px 8px;border-radius: 4px;font-size: 12px;white-space: nowrap;opacity: 0;transition: opacity 0.2s;pointer-events: none;}button:hover::after {opacity: 1;}::-webkit-scrollbar {width: 8px;}::-webkit-scrollbar-track {background-color: var(--toolbar-bg);border-radius: 4px;}::-webkit-scrollbar-thumb {background-color: var(--primary-color);border-radius: 4px;}::-webkit-scrollbar-thumb:hover {background-color: var(--hover-color);}/* 侧边栏样式 */.sidebar {flex: 0 0 250px;background-color: var(--toolbar-bg);border-radius: var(--border-radius);padding: 16px;height: calc(100vh - var(--toolbar-height) - var(--gap)*2 - 40px);overflow-y: auto;box-sizing: border-box;}.thumbnail-container {display: flex;flex-direction: column;gap: 10px;}.thumbnail-item {position: relative;cursor: pointer;border-radius: 4px;overflow: hidden;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);}.thumbnail-item canvas {width: 100%;height: auto;}.thumbnail-item.active  {border: 2px solid var(--primary-color);}.main-content {flex: 1;background-color: var(--surface-color);border-radius: var(--border-radius);/* padding: 16px; */height: calc(100vh - var(--toolbar-height) - var(--gap)*2 - 40px);box-sizing: border-box;}#pdf-container {width: 100%;height: 96%;/* height: calc(100vh - var(--toolbar-height) - var(--gap)*2 - 80px - 40px); */border: 1px solid var(--toolbar-bg);border-radius: var(--border-radius);overflow: auto;background-color: #333333;/* padding: 16px; */box-sizing: border-box;overflow-x: hidden;}.status-bar {height: 4%;font-size: 14px;color: var(--text-color);/* padding: 5px; */background-color: var(--toolbar-bg);border-radius: var(--border-radius);margin-top: auto;}.error-message {color: var(--error-color);padding: 10px;margin-top: 10px;background-color: #4d4d4d;border-radius: var(--border-radius);}/* 模态窗口样式 */.modal {display: none;position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.5);z-index: 1000;transition: opacity 0.3s ease;}.modal-content {background-color: var(--toolbar-bg);margin: 15% auto;padding: 20px;width: 80%;max-width: 500px;position: relative;border-radius: var(--border-radius);}.close {position: absolute;right: 20px;top: 10px;font-size: 28px;cursor: pointer;color: var(--text-color);}.close:hover {color: var(--primary-color);}#bookmarks-list {list-style-type: none;padding: 0;margin: 0;}#bookmarks-list li {padding: 8px;margin: 4px 0;cursor: pointer;border-radius: 4px;}#bookmarks-list li:hover {background-color: var(--primary-color);color: var(--text-color);}.modal-buttons {margin-top: 20px;}.modal-buttons button {margin: 0 5px;}canvas#pdf-canvas {position: relative;cursor: -webkit-grab;}.theme-toggle {position: relative;display: inline-block;}.light-theme {--background-color: #f9fafb; --surface-color: #ffffff;--toolbar-bg: #e5e7eb; --text-color: #374151;--error-color: #ef4444;--primary-color: #3b82f6;--hover-color: #2563eb; }.light-theme .toolbar {background-color: var(--toolbar-bg);}.light-theme .sidebar {background-color: var(--toolbar-bg);}.light-theme .main-content {background-color: var(--surface-color);}.light-theme button {background-color: var(--primary-color);color: var(--text-color);}.light-theme .status-bar {background-color: var(--toolbar-bg);}</style>
</head>
<body><div class="toolbar"><div class="logo"><img src="logo.png"  alt="Logo"></div><div class="toolbar-buttons"><button onclick="firstPage()" aria-label="首页"><span>首页</span></button><button onclick="prevPage()" aria-label="上一页"><span>上一页</span></button><button onclick="nextPage()" aria-label="下一页"><span>下一页</span></button><button onclick="lastPage()" aria-label="末页"><span>末页</span></button><button onclick="zoomOut()" aria-label="缩小"><span>缩小</span></button><input type="range" min="0.5" max="2.0" step="0.1" value="1.0" id="zoomControl"><button onclick="zoomIn()" aria-label="放大"><span>放大</span></button><button onclick="rotateClockwise()" aria-label="顺时针旋转"><span>顺时针旋转</span></button><button onclick="rotateCounterClockwise()" aria-label="逆时针旋转"><span>逆时针旋转</span></button><input type="text" id="bookmarkLabel" placeholder="输入书签名称"><button onclick="addBookmark()" aria-label="添加书签"><span>添加书签</span></button><button onclick="toggleBookmarkPanel()" aria-label="书签管理"><span>书签管理</span></button><button onclick="toggleTheme()" aria-label="切换主题" class="theme-toggle"><i class="fas fa-moon"></i></button></div></div><div class="pdf-reader-container"><div class="sidebar"><div class="thumbnail-container" id="thumbnails"></div></div><div class="main-content"><div id="pdf-container"><canvas id="pdf-canvas"></canvas></div><div class="status-bar" id="status-bar"></div></div></div><div id="bookmarks-modal" class="modal" style="display: none;"><div class="modal-content"><span class="close" onclick="closeBookmarkPanel()">&times;</span><h3>书签管理</h3><ul id="bookmarks-list"></ul><div class="modal-buttons"><button onclick="addBookmark()">添加书签</button><button onclick="clearBookmarks()">清除书签</button><button onclick="closeBookmarkPanel()">关闭</button></div></div></div><script src="pdf.min.js"></script> <script src="pdf-reader.js"></script> 
</body>
</html>

三、Javascript代码

let doc = null;
let currentPage = 1;
let scale = 1.5;
let rotation = 0;
let bookmarks = [];
let isDragging = false;
let lastX = 0;
let lastY = 0;
let offsetX = 0;
let offsetY = 0;let thumbnails = [];const thumbnailsContainer = document.getElementById('thumbnails'); const bookmarksList = document.getElementById('bookmarks-list'); 
const bookmarksPanel = document.getElementById('bookmarks-panel'); const container = document.getElementById('pdf-container'); // 新增变量用于存储当前视口的偏移量
let viewportOffsetX = 0;
let viewportOffsetY = 0;// 在window.onload 中添加键盘事件监听
window.addEventListener('keydown',  function(e) {if (e.key  === 'ArrowLeft') {prevPage();} else if (e.key  === 'ArrowRight') {nextPage();}
});// 初始化滚动条 
const zoomControl = document.getElementById('zoomControl'); 
zoomControl.value  = scale.toString(); // 初始化旋转状态 
const savedRotation = localStorage.getItem('pdfRotation'); 
if (savedRotation !== null) {rotation = parseInt(savedRotation);
}// 加载PDF文件 
function loadPDF(fileUrl) {pdfjsLib.getDocument(fileUrl).promise.then(function  (loadedDoc) {doc = loadedDoc;const numPages = doc.numPages; loadPage(currentPage);createThumbnails(numPages);// 更新状态栏 document.getElementById('status-bar').textContent  =`${currentPage} 页 / 共 ${numPages} 页 | 缩放比例: ${scale * 100}% | 旋转: ${rotation}°`;}).catch(function (error) {console.error('Error  loading PDF:', error);showError(`加载PDF时出错:${error.message}`); });
}// 创建缩略图
function createThumbnails(numPages) {thumbnailsContainer.innerHTML  = '';for (let i = 1; i <= numPages; i++) {const thumbnailItem = document.createElement('div'); thumbnailItem.className  = 'thumbnail-item';thumbnailItem.dataset.page  = i;const canvas = document.createElement('canvas'); thumbnailItem.appendChild(canvas); thumbnailsContainer.appendChild(thumbnailItem); loadThumbnail(i, canvas);thumbnailItem.addEventListener('click',  function() {currentPage = i;loadPage(currentPage);updateThumbnailsActiveState();});}
}// 更新缩略图活动状态
function updateThumbnailsActiveState() {const items = thumbnailsContainer.querySelectorAll('.thumbnail-item'); items.forEach(item  => {item.classList.remove('active'); });const currentItem = thumbnailsContainer.querySelector(`[data-page="${currentPage}"]`); if (currentItem) {currentItem.classList.add('active'); }
}// 加载指定页面 
// 修改loadPage函数
function loadPage(pageNum) {if (!doc) {showError('未加载PDF文件,请检查文件路径。');return;}doc.getPage(pageNum).then(function  (page) {while (container.firstChild)  {container.removeChild(container.firstChild); }const defaultViewport = page.getViewport({  scale: scale });const containerWidth = container.clientWidth; const containerHeight = container.clientHeight; const newScale = Math.min( containerWidth / defaultViewport.width, containerHeight / defaultViewport.height );const finalScale = Math.max(0.5,  Math.min(2.0,  newScale));const viewport = page.getViewport({ scale: scale,rotation: rotation});const canvas = document.createElement('canvas'); canvas.id  = 'pdf-canvas';container.appendChild(canvas); adjustCanvasSize(canvas, viewport);const context = canvas.getContext('2d'); if (!context) {showError('无法获取Canvas上下文,请检查浏览器支持。');return;}page.render({ canvasContext: context,viewport: viewport}).promise.then(()  => {console.log('Page  rendered successfully');hideError();// 初始化偏移量viewportOffsetX = (container.clientWidth - canvas.width) / 2;viewportOffsetY = 0;updateCanvasPosition();}).catch(error => {console.error('Error  rendering page:', error);showError(`渲染页面时出错:${error.message}`); });document.getElementById('status-bar').textContent  =`${pageNum} 页 / 共 ${doc.numPages}  页 | 缩放比例: ${Number(scale.toFixed(1))  * 100}% | 旋转: ${rotation}°`;}).catch(error => {console.error('Error  getting page:', error);showError(`获取页面时出错:${error.message}`); });}// 调整Canvas尺寸以适应页面内容 
function adjustCanvasSize(canvas, viewport) {canvas.width  = viewport.width; canvas.height  = viewport.height; const containerRect = container.getBoundingClientRect(); const canvasRect = canvas.getBoundingClientRect(); canvas.style.left  = `${(containerRect.width  - canvasRect.width)  / 2}px`;canvas.style.top  = `${(containerRect.height  - canvasRect.height)  / 2}px`;
}// 修改导航函数
function firstPage() {currentPage = 1;loadPage(currentPage);
}function prevPage() {currentPage = Math.max(1,  currentPage - 1);loadPage(currentPage);
}function nextPage() {currentPage = Math.min(doc.numPages,  currentPage + 1);loadPage(currentPage);
}function lastPage() {currentPage = doc.numPages; loadPage(currentPage);
}// 缩放功能 
function zoomIn() {scale = Math.min(2.0,  scale + 0.1);zoomControl.value  = scale.toString(); updateZoomButtons();loadPage(currentPage);
}function zoomOut() {scale = Math.max(0.5,  scale - 0.1);zoomControl.value  = scale.toString(); updateZoomButtons();loadPage(currentPage);
}// 错误提示功能 
function showError(message) {const errorDiv = document.createElement('div'); errorDiv.className  = 'error-message';errorDiv.textContent  = message;document.body.appendChild(errorDiv); 
}function hideError() {const errorDiv = document.querySelector('.error-message'); if (errorDiv) {errorDiv.remove(); }
}// 旋转功能 
function rotateClockwise() {rotation += 90;if (rotation >= 360) rotation = 0;localStorage.setItem('pdfRotation',  rotation);loadPage(currentPage);
}function rotateCounterClockwise() {rotation -= 90;if (rotation < 0) rotation += 360;localStorage.setItem('pdfRotation',  rotation);loadPage(currentPage);
}// 初始化PDF阅读器 
window.onload  = function () {const fileUrl = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf'; loadPDF(fileUrl);// 恢复旋转状态 if (savedRotation !== null) {rotation = parseInt(savedRotation);loadPage(currentPage);}// 加载保存的书签 loadSavedBookmarks();// 新增事件监听const PDF = document.getElementById('pdf-container'); console.log(PDF);PDF.addEventListener('mousedown',  startDrag);PDF.addEventListener('mousemove',  drag);PDF.addEventListener('mouseup',  stopDrag);PDF.addEventListener('wheel',  zoomWithWheel);PDF.addEventListener('dblclick',  resetPosition);const currentTheme = localStorage.getItem('theme')  || 'dark';if (currentTheme === 'light') {document.body.classList.add('light-theme'); }};// 新增拖拽功能
function startDrag(e) {if (e.button  === 0) { // 左键点击isDragging = true;lastX = e.clientX; lastY = e.clientY; }
}// 双击还原
function resetPosition(e) {canvas = document.getElementById("pdf-canvas");viewportOffsetX = (container.clientWidth - canvas.width) / 2;viewportOffsetY = 0;updateCanvasPosition();
}function drag(e) {if (isDragging) {const deltaX = e.clientX  - lastX;const deltaY = e.clientY  - lastY;// 更新偏移量viewportOffsetX += deltaX;viewportOffsetY += deltaY;// 限制偏移范围const canvas = document.getElementById('pdf-canvas'); // 更新canvas位置updateCanvasPosition();lastX = e.clientX; lastY = e.clientY; }
}function stopDrag() {isDragging = false;
}// 新增滚轮缩放功能
function zoomWithWheel(e) {e.preventDefault(); const delta = e.deltaY; if (delta > 0) {zoomOut();} else {zoomIn();}
}// 更新canvas位置
function updateCanvasPosition() {const canvas = document.getElementById('pdf-canvas'); if (canvas) {canvas.style.left  = `${viewportOffsetX}px`;canvas.style.top  = `${viewportOffsetY}px`;}
}/*** 更新缩放按钮的显示 */
function updateZoomButtons() {const buttons = document.querySelectorAll('button'); buttons.forEach(button  => {if (button.onclick  === zoomIn) {button.textContent  = `放大 (${scale.toFixed(1)})`; } else if (button.onclick  === zoomOut) {button.textContent  = `缩小 (${scale.toFixed(1)})`; }});
}/*** 处理滚动条输入事件 */
zoomControl.addEventListener('input',  function (e) {const inputValue = parseFloat(e.target.value); // 反向计算 scale 值 scale = inputValue - 0.1;updateZoomButtons();// 使用节流处理以优化性能 throttledLoadPage(currentPage);
});/*** 节流函数 * @param {function} func 目标函数 * @param {number} wait 延迟时间(毫秒)* @returns {function} 节流后的函数 */
function throttle(func, wait) {let timeout;return function (...args) {if (!timeout) {func.apply(this,  args);timeout = setTimeout(() => {timeout = null;}, wait);}};
}// 对 loadPage 进行节流处理 
const throttledLoadPage = throttle(loadPage, 100);// 监听窗口调整大小事件 
window.addEventListener('resize',  function () {if (doc && currentPage) {loadPage(currentPage);}
});// 切换书签面板显示状态 
function toggleBookmarkPanel() {const isHidden = bookmarksPanel.style.display  === 'none';bookmarksPanel.style.display  = isHidden ? 'block' : 'none';if (isHidden) {loadBookmarks();}
}// 关闭书签面板 
function closeBookmarkPanel() {bookmarksPanel.style.display  = 'none';
}// 添加当前页面为书签 
function addBookmark() {const bookmarkLabel = document.getElementById('bookmarkLabel').value.trim(); if (!bookmarkLabel) {showError('请输入书签名称');return;}const bookmark = {page: currentPage,scale: scale,label: bookmarkLabel };bookmarks.push(bookmark); saveBookmarks();loadBookmarks();document.getElementById('bookmarkLabel').value  = ''; // 清空输入框 
}// 加载并显示所有书签 
function loadBookmarks() {const bookmarksList = document.getElementById('bookmarks-list'); bookmarksList.innerHTML  = '';bookmarks.forEach((bookmark,  index) => {const li = document.createElement('li'); li.innerHTML  = `<span>${bookmark.label}</span> <button onclick="jumpToBookmark(${index})">跳转</button><button onclick="deleteBookmark(${index})">删除</button>`;li.style.backgroundColor  = '#4CAF50';li.style.color  = 'white';li.style.padding  = '8px';li.style.margin  = '4px 0';li.style.borderRadius  = '4px';bookmarksList.appendChild(li); });
}// 删除指定索引的书签 
function deleteBookmark(index) {bookmarks.splice(index,  1);saveBookmarks();loadBookmarks();
}// 清除所有书签 
function clearBookmarks() {bookmarks = [];saveBookmarks();loadBookmarks();
}// 跳转到指定书签 
function jumpToBookmark(index) {const bookmark = bookmarks[index];currentPage = bookmark.page; scale = bookmark.scale; loadPage(currentPage);
}// 保存书签到 localStorage 
function saveBookmarks() {localStorage.setItem('pdfBookmarks',  JSON.stringify(bookmarks)); 
}// 加载保存的书签 
function loadSavedBookmarks() {const saved = localStorage.getItem('pdfBookmarks'); if (saved) {bookmarks = JSON.parse(saved); loadBookmarks();}
}function toggleBookmarkPanel() {const modal = document.getElementById('bookmarks-modal'); modal.style.display  = 'block';loadBookmarks();
}function closeBookmarkPanel() {const modal = document.getElementById('bookmarks-modal'); modal.style.display  = 'none';
}// 加载缩略图
function loadThumbnail(pageNum, canvas) {doc.getPage(pageNum).then(function  (page) {const viewport = page.getViewport({  scale: 0.5 });canvas.width  = viewport.width; canvas.height  = viewport.height; const context = canvas.getContext('2d'); if (!context) return;page.render({ canvasContext: context,viewport: viewport}).promise.then(()  => {if (pageNum === currentPage) {thumbnailItem.classList.add('active'); }});});
}function toggleTheme() {document.body.classList.toggle('light-theme'); const root = document.documentElement; root.style.setProperty('--background-color',  document.body.classList.contains('light-theme')  ? '#f5f5f5' : '#1a1a1a');root.style.setProperty('--surface-color',  document.body.classList.contains('light-theme')  ? '#ffffff' : '#2d2d2d');root.style.setProperty('--toolbar-bg',  document.body.classList.contains('light-theme')  ? '#f0f0f0' : '#333333');root.style.setProperty('--text-color',  document.body.classList.contains('light-theme')  ? '#333333' : '#ffffff');root.style.setProperty('--error-color',  document.body.classList.contains('light-theme')  ? '#cc0000' : '#ff4444');}

相关文章:

Javascript网页设计案例:通过PDF.js实现一款PDF阅读器,包括预览、页面旋转、页面切换、放大缩小、黑夜模式等功能

前言 目前功能包括&#xff1a; 切换到首页。切换到尾页。上一页。下一页。添加标签。标签管理页面旋转页面随意拖动双击后还原位置 其实按照自己的预期来说&#xff0c;有很多功能还没有开发完&#xff0c;配色也没有全都搞完&#xff0c;先发出来吧&#xff0c;后期有需要…...

各类系统Pycharm安装教程

各类系统Pycharm安装教程 一、安装前的准备 1. 系统要求 操作系统: Windows:Windows 10 或更高版本(64位)。macOS:macOS 10.14 或更高版本。Linux:Ubuntu 18.04+、Fedora 30+ 等主流发行版。硬件要求: 内存:至少 4GB(推荐 8GB 以上)。磁盘空间:至少 2.5GB 可用空间…...

哈希表(C语言版)

文章目录 哈希表原理实现(无自动扩容功能)代码运行结果 分析应用 哈希表 如何统计一段文本中&#xff0c;小写字母出现的次数? 显然&#xff0c;我们可以用数组 int table[26] 来存储每个小写字母出现的次数&#xff0c;而且这样处理&#xff0c;效率奇高。假如我们想知道字…...

内容中台驱动企业数字化内容管理高效协同架构

内容概要 在数字化转型加速的背景下&#xff0c;企业对内容管理的需求从单一存储向全链路协同演进。内容中台作为核心支撑架构&#xff0c;通过统一的内容资源池与智能化管理工具&#xff0c;重塑了内容生产、存储、分发及迭代的流程。其核心价值在于打破部门壁垒&#xff0c;…...

LLaMA-Factory DeepSeek-R1 模型 微调基础教程

LLaMA-Factory 模型 微调基础教程 LLaMA-FactoryLLaMA-Factory 下载 AnacondaAnaconda 环境创建软硬件依赖 详情LLaMA-Factory 依赖安装CUDA 安装量化 BitsAndBytes 安装可视化微调启动 数据集准备所需工具下载使用教程所需数据合并数据集预处理 DeepSeek-R1 可视化微调数据集处…...

vue 文件下载(导出)excel的方法

目前有一个到处功能的需求&#xff0c;这是我用过DeepSeek生成的导出&#xff08;下载&#xff09;excel的一个方法。 1.excel的文件名是后端生成的&#xff0c;放在了响应头那里。 2.这里也可以自己制定文件名。 3.axios用的是原生的axios&#xff0c;不要用处理过的&#xff…...

【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)— 4.3 RNN与LSTM在自然语言处理中的应用案例】

咱今天来聊聊在人工智能领域里,特别重要的两个神经网络:循环神经网络(RNN)和长短时记忆网络(LSTM),主要讲讲它们在自然语言处理里的应用。你想想,平常咱们用手机和别人聊天、看新闻、听语音助手说话,背后说不定就有 RNN 和 LSTM 在帮忙呢! 二、RNN 是什么? (一)…...

LLMs Ollama

LLMs 即大型语言模型&#xff08;Large Language Models&#xff09;&#xff0c;是人工智能领域基于深度学习的重要技术&#xff0c;以下是关于它的详细介绍&#xff1a; 定义与原理 定义&#xff1a;LLMs 是一类基于深度学习的人工智能模型&#xff0c;通过海量数据和大量计…...

Blackbox.AI:高效智能的生产力工具新选择

前言 在当今数字化时代&#xff0c;一款高效、智能且功能全面的工具对于开发者、设计师以及全栈工程师来说至关重要。Blackbox.AI凭借其独特的产品特点&#xff0c;在众多生产力工具中脱颖而出&#xff0c;成为了我近期测评的焦点。以下是我对Blackbox.AI的详细测评&#xff0…...

计算机专业知识【 轻松理解数据库四大运算:笛卡尔积、选择、投影与连接】

在数据库的世界里&#xff0c;有几个关键的运算操作&#xff0c;就像是神奇的魔法工具&#xff0c;能帮助我们对数据进行各种处理和组合。今天&#xff0c;咱们就来聊聊笛卡尔积运算、选择运算、投影运算和连接运算这四大运算&#xff0c;用超简单的例子让小白也能轻松理解。 …...

C/C++字符串格式化全解析:从printf到std::format的安全演进与实战指南

目录 C 语言中的格式化函数对比 1. printf / fprintf / sprintf 的异同 C 中的字符串格式化 1. 流式输出 (std::ostringstream) 2. C20/23 格式化库 (std::format&#xff0c;需编译器支持) 跨语言对比与最佳实践 实战建议 总结 C 语言中的格式化函数对比 1. printf / …...

【C++】stack 和 queue 的适配器模式与实现

> &#x1f343; 本系列为初阶C的内容&#xff0c;如果感兴趣&#xff0c;欢迎订阅&#x1f6a9; > &#x1f38a;个人主页:[小编的个人主页])小编的个人主页 > &#x1f380; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 > ✌️ &#x1f91e; &#x1…...

【python】You-Get

文章目录 1、介绍2、安装与使用文档3、下载图片4、下载视频5、下载音乐6、参考 1、介绍 You-Get is a tiny command-line utility to download media contents (videos, audios, images) from the Web, in case there is no other handy way to do it. 源码&#xff1a;https…...

PHP基础部分

但凡是和输入、写入相关的一定要预防别人植入恶意代码! HTML部分 语句格式 <br> <hr> 分割符 <p>插入一行 按住shift 输入! 然后按回车可快速输入html代码(VsCode需要先安装live server插件) html:<h1>标题 数字越大越往后</h1> <p…...

gitee SSH 公钥设置教程

Gitee 提供了基于 SSH 协议的 Git 服务,在使用 SSH 协议访问仓库仓库之前,需要先配置好账户 SSH 公钥。 1、生成秘钥 Windows 用户建议使用 Windows PowerShell 或者 Git Bash,在 命令提示符 下无 cat 和 ls 命令。 ssh-keygen -t ed25519 -C "Gitee SSH Key"中间…...

Java零基础入门笔记:(3)程序控制

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互&#xff0c;但是Java给我们提供了这样一个工具类&…...

鸡兔同笼问题

鸡兔同笼问题是这样一个问题&#xff1a; 现有鸡、兔合装在一个笼子里。数头一共100个头&#xff0c;数脚一共300只脚。问有多少只鸡多少只兔&#xff1f; 在这里讨论这个问题的解法当然太小儿科了。但是y_tab这个C语言解释器只提供了1维数组。如果需要用到2维数组时&#xff…...

【Pytorch 库】自定义数据集相关的类

torch.utils.data.Dataset 类torch.utils.data.DataLoader 类自定义数据集示例1. 自定义 Dataset 类2. 在其他 .py 文件中引用和使用该自定义 Dataset torch_geometric.data.Dataset 类torch_geometric.data.Dataset VS torch.utils.data.Dataset 详细信息&#xff0c;参阅 tor…...

electron打包基本教程

从0开始搭建 概要步骤基础软件运行项目打包项目 注意事项 概要 将html打包成桌面的主流有electron和nwjs&#xff0c;nwjs更加简单&#xff0c;但是使用效果不如electron&#xff0c;electron打包比较麻烦&#xff0c;但是效果比较好&#xff0c;反正各有优势和缺点 步骤 基…...

实现pytorch注意力机制-one demo

主要组成部分&#xff1a; 1. 定义注意力层&#xff1a; 定义一个Attention_Layer类&#xff0c;接受两个参数&#xff1a;hidden_dim&#xff08;隐藏层维度&#xff09;和is_bi_rnn&#xff08;是否是双向RNN&#xff09;。 2. 定义前向传播&#xff1a; 定义了注意力层的…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...