Image viewer

Use grid wallpaper to highlight transparent image. Support to view the large image by holding the right mouse and drag.

目前为 2022-06-08 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Image viewer
  3. // @name:vi Image viewer
  4. // @namespace http://devs.forumvi.com/
  5. // @description Use grid wallpaper to highlight transparent image. Support to view the large image by holding the right mouse and drag.
  6. // @description:vi Sử dụng nền lưới để làm nổi bật ảnh trong suốt. Hỗ trợ xem ảnh lớn bằng cách giữ và kéo chuột phải.
  7. // @version 2.3.0
  8. // @icon http://i.imgur.com/ItcjCPc.png
  9. // @author Zzbaivong
  10. // @oujs:author baivong
  11. // @license MIT; https://baivong.mit-license.org/license.txt
  12. // @match http://*/*
  13. // @match https://*/*
  14. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
  15. // @noframes
  16. // @supportURL https://github.com/lelinhtinh/Userscript/issues
  17. // @run-at document-idle
  18. // @grant GM_addStyle
  19. // @grant GM_xmlhttpRequest
  20. // @grant GM.xmlHttpRequest
  21. // @inject-into content
  22. // ==/UserScript==
  23.  
  24. (function () {
  25. 'use strict';
  26.  
  27. /**
  28. * Background theme
  29. * @type {'system'|'dark'|'light'}
  30. */
  31. let theme = 'system';
  32.  
  33. // Do not change the code below this line, unless you know how.
  34. if (document.contentType.indexOf('image/') !== 0) return;
  35.  
  36. if (theme === 'system') {
  37. theme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
  38. }
  39. let colorGrid = theme === 'light' ? ['#eee', 'white'] : ['gray', '#444'];
  40.  
  41. function scrollByDragging(container, disableH, disableV) {
  42. function mouseUp(e) {
  43. if (e.which !== 3) return;
  44.  
  45. window.removeEventListener('mousemove', mouseMove, true);
  46. container.style.cursor = 'default';
  47. }
  48.  
  49. function mouseDown(e) {
  50. if (e.which !== 3) return;
  51.  
  52. pos = {
  53. x: e.clientX,
  54. y: e.clientY,
  55. };
  56.  
  57. window.addEventListener('mousemove', mouseMove, true);
  58. container.style.cursor = 'move';
  59. }
  60.  
  61. function mouseMove(e) {
  62. if (!disableH) container.scrollLeft -= -pos.x + (pos.x = e.clientX);
  63. if (!disableV) container.scrollTop -= -pos.y + (pos.y = e.clientY);
  64. }
  65.  
  66. let pos = {
  67. x: 0,
  68. y: 0,
  69. };
  70.  
  71. container.oncontextmenu = function (e) {
  72. e.preventDefault();
  73. };
  74.  
  75. container.addEventListener('mousedown', mouseDown, false);
  76. window.addEventListener('mouseup', mouseUp, false);
  77. }
  78.  
  79. function updateImageInfo() {
  80. let img = document.querySelector('img');
  81. if (!img) return;
  82.  
  83. let info = document.querySelector('.image-info');
  84. if (!info) {
  85. info = document.createElement('div');
  86. info.className = 'image-info';
  87. document.body.appendChild(info);
  88. }
  89.  
  90. info.innerHTML = `
  91. <div class="image-info-title">
  92. <div class="image-info-ext">${imageInfo.ext.toUpperCase()}</div>
  93. <div class="image-info-size">${imageInfo.size}</div>
  94. </div>
  95. <div class="image-info-dimensions">${imageInfo.dimensions}</div>
  96. `;
  97. }
  98.  
  99. function formatBytes(bytes, decimals = 2) {
  100. if (bytes === 0) return '0 Bytes';
  101.  
  102. const k = 1024;
  103. const dm = decimals < 0 ? 0 : decimals;
  104. const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  105.  
  106. const i = Math.floor(Math.log(bytes) / Math.log(k));
  107.  
  108. return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} <strong>${sizes[i]}</strong>`;
  109. }
  110.  
  111. GM_addStyle(
  112. `html,body{width:100%;height:100%;margin:0;padding:0}
  113. body,svg:root{background-attachment:fixed!important;background-position:0 0, 10px 10px !important;background-size:20px 20px!important;background-image:linear-gradient(45deg, ${colorGrid[0]} 25%,transparent 25%, transparent 75%,${colorGrid[0]} 75%,${colorGrid[0]} 100%),linear-gradient(45deg, ${colorGrid[0]} 25%,${colorGrid[1]} 25%,${colorGrid[1]} 75%,${colorGrid[0]} 75%,${colorGrid[0]} 100%)!important;display:flex;align-content:center;justify-content:center}
  114. body > img{background-color:transparent!important;background-image:none!important;display:block;position:initial}
  115. body > img:hover{background:rgba(0,0,0,0.4)!important;outline:3px solid #333}
  116. body > img[style*="cursor: zoom-out;"],body > img.overflowing{position:relative!important}
  117. .image-info{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#fff;background:#000000b8;text-align:center;text-shadow:1px 1px 2px #444,1px 1px 2px #444;border-radius:.2rem;padding:.4rem .7rem;width:fit-content;position:fixed;bottom:10%;left:50%;transform:translateX(-50%);opacity:1;transition:opacity 200ms;user-select:none}
  118. .image-info-title{display:flex;justify-content:space-evenly;flex-wrap:nowrap;gap:.5rem}
  119. .image-info:hover{opacity:0}
  120. .image-info-ext{font-weight:700}`,
  121. );
  122.  
  123. if (document.contentType === 'image/svg+xml') return;
  124.  
  125. scrollByDragging(document.documentElement);
  126.  
  127. const imageInfo = {
  128. ext: '',
  129. size: '',
  130. dimensions: '',
  131. };
  132.  
  133. let imageExt = document.contentType.split('/')[1];
  134. if (imageExt === 'svg+xml') imageExt = 'svg';
  135. if (imageExt === 'x-icon' || imageExt === 'vnd.microsoft.icon') imageExt = 'ico';
  136. imageInfo.ext = imageExt;
  137.  
  138. let imageDimensions = document.title.match(/\(([A-Z]{3,4} Image,\s*)?\s*([0-9]+\s*(x|×)\s*[0-9]+)\s*(\pixels\s*)?/);
  139. if (imageDimensions) imageDimensions = imageDimensions[2];
  140. imageInfo.dimensions = imageDimensions;
  141.  
  142. updateImageInfo();
  143.  
  144. GM.xmlHttpRequest({
  145. method: 'GET',
  146. url: location.href,
  147. responseType: 'arraybuffer',
  148. onload: function (response) {
  149. imageInfo.dimensions = `${document.images[0].naturalWidth${document.images[0].naturalHeight}`;
  150.  
  151. const imageSize = response.response.byteLength;
  152. imageInfo.size = formatBytes(imageSize);
  153.  
  154. updateImageInfo();
  155. },
  156. });
  157. })();

QingJ © 2025

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