您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
微信公证号文章中,图片预览
当前为
// ==UserScript== // @name img_preview // @namespace http://tampermonkey.net/ // @version 0.0.15 // @description 微信公证号文章中,图片预览 // @author Enjoy // @icon https://foruda.gitee.com/avatar/1671100286067517749/4867929_enjoy_li_1671100285.png!avatar60 // @match *://mp.weixin.qq.com/s/* // @grant GM_addElement // @grant GM_addStyle // @grant GM_setClipboard // @license GPL License // ==/UserScript== // 函数文档 https://www.tampermonkey.net/documentation.php#api:GM_addElement (function () { GM_addElement('script',{ textContent: `strFn();${strFn.toString()}` }) return function strFn() { setTimeout(() => { onImgPreview({ selector: 'img.wxw-img', backgroundColor: "rgba(0,0,0,0)" }) console.log('执行 img-preview') },5 * 1000) // onImgPreview({ // backgroundColor: "rgba(0,0,0,0)" // }) function onImgPreview(options = {}) { let defaultOptions = { eventsProxySelector: '.container', selector: 'img', showRootSelector: '#img_preview', backgroundColor: "rgba(0,0,0,0.75)", } let { eventsProxySelector, selector = 'img', showRootSelector, backgroundColor } = Object.assign({},defaultOptions,options) let scale = 1 let offset = { left: 0,top: 0 } let origin = 'center' let initialData = { offset: {}, origin: 'center', scale: 1 } let startPoint = { x: 0,y: 0 } // 记录初始触摸点位 let isTouching = false // 标记是否正在移动 let isMove = false // 正在移动中,与点击做区别 let touches = new Map() // 触摸点数组 let lastDistance = 0 let lastScale = 1 // 记录下最后的缩放值 let scaleOrigin = { x: 0,y: 0,} const { innerWidth: winWidth,innerHeight: winHeight } = window // let cloneEl = null let cloneEl = document.createElement('img') let originalEl = null /** @描述 事件委托对象 */ // (eventsProxySelector && document.querySelector(eventsProxySelector)) || let eventsProxy = window.document.body let shadow = createShadowRoot(showRootSelector) eventsProxy.addEventListener('dblclick',function (e) { console.log('e.target',e.target) let src = e.target.src || window.getComputedStyle(e.target).backgroundImage.match(/^url\("([^\s]+)"\)$/i)?.[1] if (!src) return; e.preventDefault() let findOneInPage = [...eventsProxy.querySelectorAll(selector)].find(item => item === e.target) if (findOneInPage) { let findOneInModal = [...shadow.querySelectorAll(selector)].find(item => item.src === src) if (findOneInModal) { if (!findOneInModal.classList.contains('active')) { findOneInModal.classList.add('active') return; } else { findOneInModal.remove() findOneInModal = null } } if (!findOneInModal) { originalEl = e.target originalEl.src = src cloneEl = document.createElement('img') cloneEl.src = originalEl.src // originalEl.style.opacity = 0 openPreview(shadow,cloneEl) } } else { } }) /** @描述 创建shadowbox */ function createShadowRoot(showRootSelector) { let dom = document.querySelector(`${showRootSelector}`) let shadowRoot = dom?.shadowRoot if (!dom) { dom = document.createElement('div') dom.setAttribute('id',showRootSelector.replace(/[.#]/g,'')) dom.setAttribute('style','width:0;height:0') document.documentElement.appendChild(dom) } if (!dom.shadowRoot) { shadowRoot = dom.attachShadow({ mode: 'open' }) // 创建蒙层容器 const mask = document.createElement('div') mask.classList.add('modal') mask.appendChild(createStyle()) // 添加在body下 shadowRoot.appendChild(mask) } return shadowRoot } /** @描述 创建shadowbox中的样式 */ function createStyle() { const style = document.createElement('style') style.innerHTML = `/* 图片预览 */ .modal { touch-action: none; position: fixed; z-index: 99; top: 0; left: 0; width: 100vw; height: 100vh; background-color: ${backgroundColor}; user-select: none; pointer-events: none; } .modal>*{ pointer-events: auto; } .modal>img { position: absolute; padding: 0; margin: 0; box-shadow: #09818f 0px 0px 15px 0px; border-radius: 10px; /* transition: all var(--delay_time); */ transform: translateZ(0); } img.active { animation: activeImg 0.5s 4 ease-out forwards; transition: all; } @keyframes activeImg { 0% { box-shadow: #09818f 0px 0px 15px 0px; } 50% { box-shadow: red 0px 0px 20px 0px; } 100% { box-shadow: #09818f 0px 0px 15px 0px; } } ` return style } function openPreview(shadow,cloneEl) { scale = 1 const { offsetWidth,offsetHeight } = originalEl const { top,left } = originalEl.getBoundingClientRect() console.log(`{ top,left } => %O `,{ top,left }); // 注册(不可用)事件 cloneEl.addEventListener("dblclick",dblclickFunc) cloneEl.addEventListener('mousewheel',zoom,{ passive: false }) cloneEl.addEventListener('pointerdown',onPointerdown) cloneEl.addEventListener('pointerup',onPointerup) cloneEl.addEventListener('pointermove',onPointermove) cloneEl.addEventListener('pointercancel',onPointercancel) // 遮罩点击事件 function dblclickFunc() { setTimeout(() => { if (isMove) { isMove = false } else { changeStyle(cloneEl,['transition: all .3s',`left: ${left}px`,`top: ${top}px`,`transform: translate(0,0)`,`width: ${offsetWidth}px`]) setTimeout(() => { mask.removeChild(this) originalEl.style.opacity = 1 cloneEl.removeEventListener('dblclick',dblclickFunc) },300) } },280) } // function clickFunc() { // offset = initialData.offset // origin = initialData.origin // scale = initialData.scale // changeStyle(cloneEl,[`transform: translate(${offset.left + 'px'}, ${offset.top + 'px'}) scale(${scale})`,`transform-origin: ${origin}`]) // } // 添加图片 let mask = shadow.querySelector('.modal') mask.appendChild(cloneEl) // 移动图片到屏幕中心位置 /** @描述 原图片 中心点 */ const originalCenterPoint = { x: offsetWidth / 2 + left, y: offsetHeight / 2 + top } /** @描述 页面 中心点 */ const winCenterPoint = { x: winWidth / 2, y: winHeight / 2 } console.log(`originalCenterPoint,winCenterPoint => %O `,originalCenterPoint,winCenterPoint); /** @描述 原图片中心点到页面中心点的 偏移量*/ const offsetDistance = { left: winCenterPoint.x - originalCenterPoint.x + left, top: winCenterPoint.y - originalCenterPoint.y + top } /** @描述 放大后的 */ const diffs = { left: ((adaptScale() - 1) * offsetWidth) / 2, top: ((adaptScale() - 1) * offsetHeight) / 2 } console.log(`offsetDistance2 => %O `,JSON.parse(JSON.stringify(offsetDistance)),JSON.parse(JSON.stringify(diffs))); changeStyle(cloneEl,[`left: ${left}px`,`top: ${top}px`]) changeStyle(cloneEl,['transition: all 0.3s',`width: ${offsetWidth * adaptScale() + 'px'}`,`transform: translate(${offsetDistance.left - left - diffs.left}px, ${offsetDistance.top - top - diffs.top}px)`]) /** @描述 消除偏差:让图片相对于window 0 0定位,通过translate设置中心点重合*/ setTimeout(() => { changeStyle(cloneEl,['transition: all 0s',`left: 0`,`top: 0`,`transform: translate(${offsetDistance.left - diffs.left}px, ${offsetDistance.top - diffs.top}px)`]) console.log(`offsetDistance3 => %O `,offsetDistance,diffs); offset = { left: offsetDistance.left - diffs.left, top: offsetDistance.top - diffs.top } // 记录值 record() },300) } // 滚轮缩放 const zoom = (event) => { if (!event.deltaY) { return } event.preventDefault() origin = `${event.offsetX}px ${event.offsetY}px` // 缩放执行 if (event.deltaY < 0) { scale += 0.1 // 放大 } else if (event.deltaY > 0) { scale >= 0.2 && (scale -= 0.1) // 缩小 } if (scale < initialData.scale) { reduction() } offset = getOffsetCorrection(event.offsetX,event.offsetY) changeStyle(cloneEl,['transition: all .15s',`transform-origin: ${origin}`,`transform: translate(${offset.left + 'px'}, ${offset.top + 'px'}) scale(${scale})`]) } // 获取中心改变的偏差 function getOffsetCorrection(x = 0,y = 0) { const touchArr = Array.from(touches) if (touchArr.length === 2) { const start = touchArr[0][1] const end = touchArr[1][1] x = (start.offsetX + end.offsetX) / 2 y = (start.offsetY + end.offsetY) / 2 } origin = `${x}px ${y}px` const offsetLeft = (scale - 1) * (x - scaleOrigin.x) + offset.left const offsetTop = (scale - 1) * (y - scaleOrigin.y) + offset.top scaleOrigin = { x, y } return { left: offsetLeft, top: offsetTop } } // 操作事件 function onPointerdown(e) { e.preventDefault() touches.set(e.pointerId,e) // TODO: 点击存入触摸点 isTouching = true startPoint = { x: e.clientX, y: e.clientY } if (touches.size === 2) { // TODO: 判断双指触摸,并立即记录初始数据 lastDistance = getDistance() lastScale = scale } } // window.addEventListener('pointerdown',onPointerdown) // window.addEventListener('pointerup',onPointerup) // window.addEventListener('pointermove',onPointermove) // window.addEventListener('pointercancel',onPointercancel) function onPointerup(e) { touches.delete(e.pointerId) // TODO: 抬起移除触摸点 if (touches.size <= 0) { isTouching = false } else { const touchArr = Array.from(touches) // 更新点位 startPoint = { x: touchArr[0][1].clientX, y: touchArr[0][1].clientY } } setTimeout(() => { isMove = false },300); } function onPointermove(e) { e.preventDefault() if (isTouching) { isMove = true if (touches.size < 2) { // 单指滑动 offset = { left: offset.left + (e.clientX - startPoint.x), top: offset.top + (e.clientY - startPoint.y), } changeStyle(cloneEl,['transition: all 0s',`transform: translate(${offset.left + 'px'}, ${offset.top + 'px'}) scale(${scale})`,`transform-origin: ${origin}`]) // 更新点位 startPoint = { x: e.clientX, y: e.clientY } } else { // 双指缩放 touches.set(e.pointerId,e) const ratio = getDistance() / lastDistance scale = ratio * lastScale offset = getOffsetCorrection() if (scale < initialData.scale) { reduction() } changeStyle(cloneEl,['transition: all 0s',`transform: translate(${offset.left + 'px'}, ${offset.top + 'px'}) scale(${scale})`,`transform-origin: ${origin}`]) } } } function onPointercancel(e) { touches.clear() // 可能存在特定事件导致中断,真机操作时 pointerup 在某些边界情况下不会生效,所以需要清空 } // 修改样式,减少回流重绘 function changeStyle(el,arr) { // console.log(`el.style.cssText => %O `,el.style.cssText,arr); const original = el.style.cssText.split(';') original.pop() // console.log(` original.concat(arr).join(';') + ';' => %O `, original.concat(arr).join(';') + ';'); el.style.cssText = original.concat(arr).join(';') + ';' } // 计算自适应屏幕的缩放 function adaptScale() { const { offsetWidth: w,offsetHeight: h } = originalEl let scale = winWidth / w if (h * scale > winHeight - 80) { scale = (winHeight - 80) / h } return scale } // 获取距离 function getDistance() { const touchArr = Array.from(touches) if (touchArr.length < 2) { return 0 } const start = touchArr[0][1] const end = touchArr[1][1] return Math.hypot(end.x - start.x,end.y - start.y) } // 记录初始化数据 function record() { initialData = Object.assign({},{ offset, origin, scale }) } // 还原记录,用于边界处理 let timer = null function reduction() { timer && clearTimeout(timer) timer = setTimeout(() => { // offset = initialData.offset // origin = initialData.origin // scale = initialData.scale changeStyle(cloneEl,[`transform: translate(${offset.left + 'px'}, ${offset.top + 'px'}) scale(${scale})`,`transform-origin: ${origin}`]) },300) } } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址