Image Preview

preview any image

  1. // ==UserScript==
  2. // @name Image Preview
  3. // @version 0.5
  4. // @license MIT
  5. // @description preview any image
  6. // @author You
  7. // @match https://mp.weixin.qq.com/s*
  8. // @match https://xie.infoq.cn/article/*
  9. // @match https://hacks.mozilla.org/*
  10. // @match https://aotu.io/notes/*
  11. // @match https://7kms.github.io/*
  12. // @require https://cdn.jsdelivr.net/npm/vue@2.6.11
  13.  
  14. // @grant none
  15. // @namespace https://mp.weixin.qq.com/s/*
  16. // ==/UserScript==
  17.  
  18. (function () {
  19. // 针对本身是图片的,则不使用
  20. function shouldIgnore() {
  21. return /\.(png|jpg|jpeg|svg|gif|webp)$/.test(location.href);
  22. }
  23.  
  24. function initMountedNode() {
  25. // 插入DOM元素
  26. const imgPreviewContainer = document.createElement('div');
  27. imgPreviewContainer.setAttribute('class', 'img-preview-container');
  28. document.body.appendChild(imgPreviewContainer);
  29. return imgPreviewContainer;
  30. }
  31.  
  32. function mount(el) {
  33. // 图片预览组件
  34. Vue.component('img-preview', {
  35. props: {
  36. // 是否显示
  37. isShow: {
  38. type: Boolean,
  39. required: true,
  40. default: false,
  41. },
  42.  
  43. // 图片url
  44. picUrl: {
  45. type: String,
  46. default: '',
  47. },
  48. },
  49. template: `<transition name="scale">
  50. <div v-if="isShow && picUrl" class="img-view-wrapper" @click.stop="$emit('update:isShow', false)">
  51. <img class="img-view" :src="picUrl" alt="not image" />
  52. </div>
  53. </transition>`,
  54. methods: {
  55. // 固定body不让其滚动
  56. fixedBody() {
  57. document.body.style.overflow = 'hidden';
  58. },
  59. // 释放body,让其滚动
  60. looseBody() {
  61. document.body.style.overflow = 'auto';
  62. },
  63. },
  64. watch: {
  65. isShow(val) {
  66. if (val) {
  67. // 展示
  68. this.fixedBody();
  69. } else {
  70. this.looseBody();
  71. }
  72. },
  73. },
  74. });
  75.  
  76. // 挂载
  77. const vm = new Vue({
  78. el,
  79. data: {
  80. picUrl: '',
  81. isShowImgPreview: false,
  82. },
  83. template: '<img-preview :pic-url="picUrl" :is-show.sync="isShowImgPreview" />',
  84. created() {
  85. // 冒泡阶段处理,避免有些网站把事件拦截掉了
  86. document.addEventListener(
  87. 'click',
  88. (ev) => {
  89. const img = ev.target;
  90. const { nodeName } = img;
  91. if (nodeName === 'IMG') {
  92. // 图片
  93. this.picUrl = img.getAttribute('src');
  94. this.isShowImgPreview = true;
  95. }
  96. },
  97. true
  98. );
  99. },
  100. });
  101. }
  102.  
  103. // 添加样式
  104. function addStyle() {
  105. const style = document.createElement('style');
  106. style.innerHTML = `
  107. .img-view-wrapper {
  108. display: flex;
  109. justify-content: center;
  110. align-items: center;
  111. position: fixed;
  112. top: 0;
  113. left: 0;
  114. width: 100vw;
  115. height: 100vh;
  116. overflow: auto;
  117. z-index: 99999 !important;
  118. background: rgba(0, 0, 0, 0.6);
  119. }
  120.  
  121. .img-view {
  122. cursor: zoom-out;
  123. max-width: 100%;
  124. max-height: 100%;
  125. }
  126.  
  127. .scale-enter-active,
  128. .scale-leave-active {
  129. transition: all 0.4s;
  130. }
  131.  
  132. .scale-enter,
  133. .scale-leave-to {
  134. transform: scale(0);
  135. }`;
  136. document.head.appendChild(style);
  137. }
  138.  
  139. function main() {
  140. if (shouldIgnore()) {
  141. return;
  142. }
  143.  
  144. const el = initMountedNode();
  145. addStyle();
  146. mount(el);
  147. }
  148.  
  149. main();
  150. })();

QingJ © 2025

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