网页快速打印软件

帮助用户实现快速打印,在任意网页上添加一个悬浮且可拖动的打印按钮。功能:自动折叠、菜单控制、位置和状态记忆。优点:易用性强、提高效率、可自定义、跨页面持久化、快速打印。

  1. // ==UserScript==
  2. // @name 网页快速打印软件
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.4.1
  5. // @description 帮助用户实现快速打印,在任意网页上添加一个悬浮且可拖动的打印按钮。功能:自动折叠、菜单控制、位置和状态记忆。优点:易用性强、提高效率、可自定义、跨页面持久化、快速打印。
  6. // @author wll
  7. // @match *://*/*
  8. // @grant GM_registerMenuCommand
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @license AGPL-3.0-or-later
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. let isButtonVisible = true;
  18. let isCollapsed = false;
  19. let draggedFromRight = false;
  20.  
  21. // 加载按钮的位置信息
  22. async function loadButtonPosition() {
  23. const left = await GM_getValue('printButtonLeft', '0px');
  24. const top = await GM_getValue('printButtonTop', '50%');
  25. const right = await GM_getValue('printButtonRight', '');
  26. isCollapsed = await GM_getValue('printButtonIsCollapsed', false);
  27. draggedFromRight = await GM_getValue('printButtonDraggedFromRight', false);
  28. return { left, top, right, isCollapsed, draggedFromRight };
  29. }
  30.  
  31. // 创建按钮
  32. const button = document.createElement('div');
  33. button.textContent = '打印';
  34. button.style.position = 'fixed';
  35. button.style.transform = 'translateY(-50%)';
  36. button.style.backgroundColor = '#007bff';
  37. button.style.color = 'white';
  38. button.style.padding = '10px';
  39. button.style.borderRadius = '5px';
  40. button.style.cursor = 'pointer';
  41. button.style.zIndex = '9999';
  42. button.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';
  43. button.style.transition = 'left 0.3s, right 0.3s, width 0.3s, height 0.3s, padding 0.3s';
  44.  
  45. // 创建拖动标识
  46. const dragIndicator = document.createElement('div');
  47. dragIndicator.style.position = 'absolute';
  48. dragIndicator.style.top = '0';
  49. dragIndicator.style.right = '0';
  50. dragIndicator.style.bottom = '0';
  51. dragIndicator.style.left = '0';
  52. dragIndicator.style.border = '2px dashed #fff';
  53. dragIndicator.style.borderRadius = '5px';
  54. dragIndicator.style.display = 'none';
  55.  
  56. button.appendChild(dragIndicator);
  57. document.body.appendChild(button);
  58.  
  59. loadButtonPosition().then((position) => {
  60. button.style.top = position.top;
  61. button.style.left = position.draggedFromRight ? '' : position.left;
  62. button.style.right = position.draggedFromRight ? '0px' : position.right;
  63.  
  64. // 恢复折叠状态
  65. if (position.isCollapsed) {
  66. collapseButton();
  67. }
  68. });
  69.  
  70. // 拖动功能
  71. let isDragging = false;
  72. let offsetX, offsetY;
  73. let autoCollapseTimeout;
  74.  
  75. button.addEventListener('mousedown', (e) => {
  76. isDragging = true;
  77. offsetX = e.clientX - button.getBoundingClientRect().left;
  78. offsetY = e.clientY - button.getBoundingClientRect().top;
  79. clearTimeout(autoCollapseTimeout);
  80. expandButton();
  81. dragIndicator.style.display = 'block';
  82.  
  83. // 防止选中网页其他信息
  84. e.preventDefault();
  85. });
  86.  
  87. document.addEventListener('mousemove', (e) => {
  88. if (isDragging) {
  89. let newX = e.clientX - offsetX;
  90. let newY = e.clientY - offsetY;
  91.  
  92. // 确保按钮不会超出网页边框
  93. newX = Math.max(0, Math.min(newX, window.innerWidth - button.offsetWidth));
  94. newY = Math.max(0, Math.min(newY, window.innerHeight - button.offsetHeight));
  95.  
  96. button.style.left = `${newX}px`;
  97. button.style.right = ''; // 清除右边的属性
  98. button.style.top = `${newY}px`;
  99.  
  100. // 判断是否从右边拖动
  101. draggedFromRight = newX > (window.innerWidth - button.offsetWidth) / 2;
  102. }
  103. });
  104.  
  105. document.addEventListener('mouseup', () => {
  106. if (isDragging) {
  107. isDragging = false;
  108. saveButtonPosition();
  109. startAutoCollapseTimer();
  110. dragIndicator.style.display = 'none';
  111. }
  112. });
  113.  
  114. // 自动折叠功能
  115. function startAutoCollapseTimer() {
  116. clearTimeout(autoCollapseTimeout);
  117. autoCollapseTimeout = setTimeout(() => {
  118. collapseButton();
  119. }, 5000);
  120. }
  121.  
  122. function collapseButton() {
  123. const rect = button.getBoundingClientRect();
  124. if (rect.left + rect.width / 2 < window.innerWidth / 2) {
  125. button.style.left = '0px';
  126. button.style.right = '';
  127. button.style.width = '20px';
  128. button.style.height = '40px';
  129. button.style.backgroundColor = '#007bff';
  130. button.style.color = 'white';
  131. button.style.borderRadius = '0 20px 20px 0'; // 改为向右的半圆
  132. button.style.textAlign = 'center';
  133. button.innerHTML = '&#x25B6;'; // 右箭头
  134. } else {
  135. button.style.right = '0px';
  136. button.style.left = '';
  137. button.style.width = '20px';
  138. button.style.height = '40px';
  139. button.style.backgroundColor = '#007bff';
  140. button.style.color = 'white';
  141. button.style.borderRadius = '20px 0 0 20px'; // 改为向左的半圆
  142. button.style.textAlign = 'center';
  143. button.innerHTML = '&#x25C0;'; // 左箭头
  144. }
  145. isCollapsed = true;
  146. saveButtonPosition();
  147. }
  148.  
  149. function expandButton(isFromMouseEnter = false) {
  150. if (isCollapsed) {
  151. button.style.width = '';
  152. button.style.height = '';
  153. button.style.backgroundColor = '#007bff';
  154. button.style.color = 'white';
  155. button.style.borderRadius = '5px';
  156. button.textContent = '打印';
  157. if (isFromMouseEnter) {
  158. const rect = button.getBoundingClientRect();
  159. if (rect.left === 0) {
  160. button.style.left = '0px';
  161. button.style.right = '';
  162. } else if (rect.right === 0) {
  163. button.style.right = '0px';
  164. button.style.left = '';
  165. }
  166. }
  167. isCollapsed = false;
  168. }
  169. }
  170.  
  171. button.addEventListener('mouseenter', () => {
  172. clearTimeout(autoCollapseTimeout);
  173. if (isCollapsed) {
  174. expandButton(true);
  175. }
  176. });
  177.  
  178. button.addEventListener('mouseleave', () => {
  179. startAutoCollapseTimer();
  180. });
  181.  
  182. // 打印功能
  183. button.addEventListener('click', (e) => {
  184. if (!isDragging) { // 只有在未拖动时才执行打印
  185. window.print();
  186. }
  187. });
  188.  
  189. // 保存按钮位置信息
  190. async function saveButtonPosition() {
  191. await GM_setValue('printButtonLeft', button.style.left);
  192. await GM_setValue('printButtonTop', button.style.top);
  193. await GM_setValue('printButtonRight', button.style.right);
  194. await GM_setValue('printButtonIsCollapsed', isCollapsed);
  195. await GM_setValue('printButtonDraggedFromRight', draggedFromRight);
  196. }
  197.  
  198. // 初始化自动折叠计时器
  199. startAutoCollapseTimer();
  200.  
  201. // 注册(不可用)菜单命令
  202. GM_registerMenuCommand('显示/隐藏打印按钮', toggleButtonVisibility);
  203.  
  204. async function toggleButtonVisibility() {
  205. isButtonVisible = !isButtonVisible;
  206. button.style.display = isButtonVisible ? 'block' : 'none';
  207. if (isButtonVisible) {
  208. const position = await loadButtonPosition();
  209. button.style.top = position.top;
  210. button.style.left = position.draggedFromRight ? '' : position.left;
  211. button.style.right = position.draggedFromRight ? '0px' : position.right;
  212.  
  213. // 恢复折叠状态
  214. if (position.isCollapsed) {
  215. collapseButton();
  216. }
  217. }
  218. }
  219. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址