您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Compare images
当前为
// ==UserScript== // @name Easy Compare // @description Compare images // @version 0.2 // @author Secant (TYT@NexusHD) // @license GPL-3.0-or-later // @supportURL [email protected] // @contributionURL https://i.loli.net/2020/02/28/JPGgHc3UMwXedhv.jpg // @contributionAmount 10 // @include * // @require https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js // @require https://bundle.run/[email protected] // /require https://cdn.staticfile.org/pako/1.0.10/pako.min.js // /require https://cdn.staticfile.org/upng-js/2.1.0/UPNG.min.js // @namespace https://gf.qytechs.cn/users/152136 // @icon data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23008000'%3E%3Cpath id='ld' d='M20 6H10c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h10v4h4V2h-4v4zm0 30H10l10-12v12zM38 6H28v4h10v26L28 24v18h10c2.21 0 4-1.79 4-4V10c0-2.21-1.79-4-4-4z'/%3E%3C/svg%3E // @grant GM_xmlhttpRequest // @grant unsafewindow // @connect hdbits.org // @connect awesome-hd.me // @connect ptpimg.me // @connect imgbox.com // @connect malzo.com // @connect imagebam.com // @connect pixhost.to // @connect loli.net // @connect funkyimg.com // @connect ilikeshots.club // @connect * // ==/UserScript== // # TODO List // ☑ image diff: https://bundle.run/[email protected] // this is a compation intensive operation, // so dataURL dynamic webwoker is used. // ☐ canvasless (async/sync) // ☐ more sites support // ☑ guess images // ☑ redirect url chopper: deferer, anonymouse // jshint esversion:8 (function ($, Mousetrap, pixelmatch, UPNG, URL) { 'use strict'; // Web Worker Initialization let workerDataURL = `data:application/javascript,${encodeURIComponent(`const defaultOptions={threshold:.1,includeAA:!1,alpha:.1,aaColor:[255,255,0],diffColor:[255,0,0],diffMask:!1};function pixelmatch(a,b,c,d,e,f){if(!isPixelData(a)||!isPixelData(b)||c&&!isPixelData(c))throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected.");if(a.length!==b.length||c&&c.length!==a.length)throw new Error("Image sizes do not match.");if(a.length!==4*(d*e))throw new Error("Image data size does not match width/height.");f=Object.assign({},defaultOptions,f);const g=d*e,h=new Uint32Array(a.buffer,a.byteOffset,g),j=new Uint32Array(b.buffer,b.byteOffset,g);let k=!0;for(let l=0;l<g;l++)if(h[l]!==j[l]){k=!1;break}if(k){if(c&&!f.diffMask)for(let b=0;b<g;b++)drawGrayPixel(a,4*b,f.alpha,c);return 0}const l=35215*f.threshold*f.threshold;let m=0;const[n,o,p]=f.aaColor,[q,r,s]=f.diffColor;for(let g=0;g<e;g++)for(let h=0;h<d;h++){const i=4*(g*d+h),j=colorDelta(a,b,i,i);j>l?!f.includeAA&&(antialiased(a,h,g,d,e,b)||antialiased(b,h,g,d,e,a))?c&&!f.diffMask&&drawPixel(c,i,n,o,p):(c&&drawPixel(c,i,q,r,s),m++):c&&!f.diffMask&&drawGrayPixel(a,i,f.alpha,c)}return m}function isPixelData(a){return ArrayBuffer.isView(a)&&1===a.constructor.BYTES_PER_ELEMENT}function antialiased(a,b,c,d,e,f){const g=Math.max(b-1,0),h=Math.max(c-1,0),i=Math.min(b+1,d-1),j=Math.min(c+1,e-1);let k,l,m,n,o=b===g||b===i||c===h||c===j?1:0,p=0,q=0;for(let r=g;r<=i;r++)for(let e=h;e<=j;e++){if(r===b&&e===c)continue;const f=colorDelta(a,a,4*(c*d+b),4*(e*d+r),!0);if(0!==f)f<p?(p=f,k=r,l=e):f>q&&(q=f,m=r,n=e);else if(o++,2<o)return!1}return 0!==p&&0!==q&&(hasManySiblings(a,k,l,d,e)&&hasManySiblings(f,k,l,d,e)||hasManySiblings(a,m,n,d,e)&&hasManySiblings(f,m,n,d,e))}function hasManySiblings(a,b,c,d,e){const f=Math.max(b-1,0),g=Math.max(c-1,0),h=Math.min(b+1,d-1),i=Math.min(c+1,e-1),j=4*(c*d+b);let k=b===f||b===h||c===g||c===i?1:0;for(let l=f;l<=h;l++)for(let e=g;e<=i;e++){if(l===b&&e===c)continue;const f=4*(e*d+l);if(a[j]===a[f]&&a[j+1]===a[f+1]&&a[j+2]===a[f+2]&&a[j+3]===a[f+3]&&k++,2<k)return!0}return!1}function colorDelta(a,b,c,d,e){let f=a[c+0],g=a[c+1],h=a[c+2],j=a[c+3],k=b[d+0],l=b[d+1],m=b[d+2],n=b[d+3];if(j===n&&f===k&&g===l&&h===m)return 0;255>j&&(j/=255,f=blend(f,j),g=blend(g,j),h=blend(h,j)),255>n&&(n/=255,k=blend(k,n),l=blend(l,n),m=blend(m,n));const o=rgb2y(f,g,h)-rgb2y(k,l,m);if(e)return o;const p=rgb2i(f,g,h)-rgb2i(k,l,m),i=rgb2q(f,g,h)-rgb2q(k,l,m);return .5053*o*o+.299*p*p+.1957*i*i}function rgb2y(a,c,d){return .29889531*a+.58662247*c+.11448223*d}function rgb2i(a,c,d){return .59597799*a-.2741761*c-.32180189*d}function rgb2q(a,c,d){return .21147017*a-.52261711*c+.31114694*d}function blend(b,c){return 255+(b-255)*c}function drawPixel(a,c,d,e,f){a[c+0]=d,a[c+1]=e,a[c+2]=f,a[c+3]=255}function drawGrayPixel(a,c,d,e){const f=a[c+0],h=a[c+1],g=a[c+2],b=blend(rgb2y(f,h,g),d*a[c+3]/255);drawPixel(e,c,b,b,b)}self.onmessage=a=>{img1=new Uint8ClampedArray(a.data.img1),img2=new Uint8ClampedArray(a.data.img2),diff=new Uint8ClampedArray(img1),width=a.data.width,height=a.data.height,init=a.data.init,key=a.data.key;try{pixelmatch(img1,img2,diff,width,height,init),self.postMessage({diff:diff.buffer,key:key},[diff.buffer])}catch(a){console.warn(a),self.postMessage({diff:null,key:key})}};`)}`; let diffWorker; try { diffWorker = new Worker(workerDataURL); diffWorker.keyPool = {}; } catch (e) { diffWorker = null; } // Title: Mousetrap Pause Plugin // Reference: https://github.com/ccampbell/mousetrap/tree/master/plugins/pause if (Mousetrap) { let target = Mousetrap.prototype || Mousetrap; const _originalStopCallback = target.stopCallback; target.stopCallback = function (e, element, combo) { var self = this; if (self.paused) { return true; } return _originalStopCallback.call(self, e, element, combo); }; target.pause = function () { var self = this; self.paused = true; }; target.unpause = function () { var self = this; self.paused = false; }; } // A global timeout ID holder let timeout; // Regex replacement array that converts thumbs to originals const t2oLib = [ [/\.thumb\.jpe?g$/, ''], // nexusphp [/\.md\.png$/, '.png'], // m-team [/\.th\.png$/, '.png'], // pterclub [/_thumb\.png$/, '.png'], // totheglory [/img\.awesome\-hd\.me\/t(\/\d+)?\//, 'img.awesome-hd.me/images/'], // awesome-hd [/thumbs((?:\d+)?\.imgbox\.com\/.+_)t\.png$/, 'images$1o.png'], // imgbox [/t((?:\d+)?\.pixhost\.to\/)thumbs\//, 'img$1images/'], // pixhost [/t(\.hdbits\.org\/.+)\.jpg$/, 'i$1.png'], // hdbits ]; // Skip redirections const skipRedirLib = [ [/^https?:\/\/anonym\.to\/\?(.*)$/, (_, p1) => decodeURIComponent(p1)], [/^https?:\/\/www\.dereferer\.org\/\?(.*)$/, (_, p1) => decodeURIComponent(p1)] ]; // Probable original image selectors on a view page const guessSelectorLib = [ '#image-viewer-container>img', '.image-container img', 'div.img.big>img', 'img.mainimage', 'img#img' ]; // Guess original image src from view page function guessOriginalImage(url) { return new Promise((resolve) => { GM_xmlhttpRequest({ url: url, method: 'GET', timeout: 6000, onload: (x) => { if (x.status === 200) { try { const $e = $$(x.responseText); const src = $e.find(guessSelectorLib.join(','))[0].src; let realSrc = src; for (let pairs of t2oLib) { realSrc = realSrc.replace(pairs[0], pairs[1]); if (realSrc !== src) { break; } } resolve(realSrc); } catch (e) { console.warn(e); resolve(null); } } else { console.warn(x); resolve(null); } }, ontimeout: (e) => { console.warn(e); resolve(null); } }); }); } // Get image uint8 array buffer async function getImageBytesBuffer(src, fn) { const imageArrayBuffer = await new Promise((resolve) => { GM_xmlhttpRequest({ url: src, method: 'GET', responseType: 'arraybuffer', onprogress: (e) => { if (e.total !== -1) { fn(e.loaded / e.total); } else { fn(-e.loaded); } }, onload: (e) => { if (e.status === 200) { resolve(e.response); } else { console.warn(e); resolve(null); } }, onerror: (e) => { console.warn(e); resolve(null); } }); }); if (imageArrayBuffer) { /* const upngObj = UPNG.decode(imageArrayBuffer); console.log(upngObj); if(upngObj.data) { return { raw: upngObj.data, width: upngObj.width, height: upngObj.height }; } else { return null; } */ return new Promise(async (resolve) => { const url = await new Promise((resolve) => { const fr = new FileReader(); fr.onload = e => resolve(fr.result); fr.readAsDataURL(new Blob([new Uint8Array(imageArrayBuffer)], { type: 'image/png' })); }); const img = new Image(); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); img.onload = function () { const [width, height] = [this.width, this.height]; canvas.width = width; canvas.height = height; context.drawImage(this, 0, 0, width, height); resolve({ raw: context.getImageData(0, 0, width, height).data.buffer, width: width, height: height }); }; img.onerror = function () { resolve(null); }; img.src = url; }); } else { return null; } } // Diff images (async or sync) // input: src1, src2, on progress function, pixelmatch initilization object, web worker // ouput: diffsrc (dataURL) async function diffThem(src1, src2, onprogress, init = { alpha: 0.5, threshold: 0.007 }, worker = diffWorker) { const [img1, img2] = await Promise.all([ getImageBytesBuffer(src1, (p) => onprogress(p, 0)), getImageBytesBuffer(src2, (p) => onprogress(p, 1)) ]); if ( img1 && img2 && img1.width === img2.width && img1.height === img2.height ) { onprogress(null, null); const [raw1, raw2, width, height] = [img1.raw, img2.raw, img1.width, img1.height]; if (worker) {// async diff const key = '' + Date.now(); worker.onmessage = (e) => { const returnKey = e.data.key; const resolve = worker.keyPool[returnKey]; if (resolve) { const canvas = document.createElement('canvas'); [canvas.width, canvas.height] = [width, height]; const context = canvas.getContext('2d'); context.putImageData(new ImageData( new Uint8ClampedArray(e.data.diff), width, height ), 0, 0); resolve(canvas.toDataURL('image/png', 1)); delete worker.keyPool[returnKey]; } }; worker.postMessage({ img1: raw1, img2: raw2, width: width, height: height, init: init, key: key }, [raw1, raw2]); return new Promise((res) => { worker.keyPool[key] = res; }); } else {// sync diff const [raw1, raw2, width, height] = [ new Uint8ClampedArray(img1.raw), new Uint8ClampedArray(img2.raw), img1.width, img1.height ]; const canvas = document.createElement('canvas'); [canvas.width, canvas.height] = [width, height]; const context = canvas.getContext('2d'); const diff = context.createImageData(width, height); pixelmatch(raw1, raw2, diff.data, width, height, init); context.putImageData(diff, 0, 0); return canvas.toDataURL('image/png', 1); } } else { return null; } } // Virtual DOM for selection without fetching images function $$(htmlString) { return $(htmlString, document.implementation.createHTMLDocument('virtual')); } // Convert text to SVG image function text2SVGDataURL(text, width, height = 20) { return `data:image/svg+xml,${ encodeURIComponent( `<svg xmlns='http://www.w3.org/2000/svg' height="${height}" width="${width}"><text x="0" y="15" fill="white">${text}</text></svg>` )}`; } // Function to make an <img/> element function makeImage(src, outlineColor = 'red') { return $(`<img src="${src}"/>`).css({ 'display': 'none', 'top': '50%', 'left': '50%', 'position': 'fixed', 'transform': 'translate(-50%, -50%)', 'opacity': '1', 'outline': '3px solid ' + outlineColor, 'outline-offset': '2px', 'vertical-align': 'middle' }); } // Function fired when compare button is activated function activateCompare($target) { $target.attr({ 'fill': '#008000' }).css({ 'cursor': 'pointer', 'opacity': '1' })[0].state = true; } // Function fired when leaving image function leaveImage($overlay, target = undefined) { const original = $overlay.find('img:visible').hide()[0]; if (target || (original && (target = original.targetImage))) { $(target).css('box-shadow', target.boxShadow); } } // Function fired when compare button is clicked and toggled on function enterCompare($overlay, $images, $message) { if (Mousetrap) { Mousetrap.pause(); } $overlay.show()[0].state = true; let colors = ['red', 'blue']; let step = 1, baseImage, threshold = 0.007; $images.toArray().forEach((target) => { target.boxShadow = $(target).css('box-shadow'); Object.defineProperty(target, target.src, { get() { const hiddenProp = '_' + target.src; if (!target[hiddenProp]) { let realSrc = target.src; for (let pairs of t2oLib) { realSrc = realSrc.replace(pairs[0], pairs[1]); if (realSrc !== target.src) { break; } } const originalImage = makeImage(text2SVGDataURL(`Loading...`, 80), colors[0])[0]; originalImage.ready = false; originalImage.targetImage = target; $overlay.append(originalImage); target[hiddenProp] = originalImage; let href, hrefOriginal; if (realSrc === target.src && (hrefOriginal = target.parentElement.href, href = hrefOriginal) && !href.match(/\.png$|\.jpe?g$|\.webp$/)) { for (let pairs of skipRedirLib) { href = href.replace(pairs[0], pairs[1]); if (href !== hrefOriginal) { break; } } guessOriginalImage(href) .then(src => { originalImage.src = src || realSrc; originalImage.ready = true; }); } else if (href && href.match(/\.png$|\.jpe?g$|\.webp$/)) { originalImage.src = href; originalImage.ready = true; } else { originalImage.src = realSrc; originalImage.ready = true; } } $(target[hiddenProp]).css({ 'outline-color': colors[0] }); return target[hiddenProp]; }, configurable: true }); }); $images.on('mouseenter.compare', (e, triggeredShiftKey) => { const target = e.currentTarget; clearTimeout(timeout); leaveImage($overlay); $(target).css({ 'box-shadow': '0px 0px 8px ' + colors[0] }); if ((e.shiftKey || triggeredShiftKey) && baseImage && baseImage[baseImage.src].ready && target[target.src].ready) { const bimg = baseImage; if (!target[bimg.src]) { const diffImage = makeImage(text2SVGDataURL(`Loading ...`, 80), colors[0])[0]; diffImage.threshold = -1; diffImage.step = 0.001; $overlay.append(diffImage); target[bimg.src] = diffImage; bimg[target.src] = diffImage; let progress = [0, 0]; const updateProgress = (p, ind) => { if (p !== null && p >= 0 && ind !== null) { progress[ind] = p; diffImage.src = text2SVGDataURL(`Loading ${((progress[0] + progress[1]) * 50).toFixed(1)}%`, 120); } else if (p < 0) { diffImage.src = text2SVGDataURL(`Loading...`, 80); } else { diffImage.src = text2SVGDataURL(`Diffing...`, 80); } }; diffThem(bimg[bimg.src].src, target[target.src].src, updateProgress, { alpha: 0.5, threshold: threshold }) .then((diffSrc) => { if (diffSrc === null) { diffImage.src = text2SVGDataURL(`Sizes Not Match`, 120); } else { diffImage.src = diffSrc; diffImage.threshold = threshold; } }); } target[bimg.src].baseImage = bimg; target[bimg.src].targetImage = target; $(target[bimg.src]).show(); } else { $(target[target.src]).show(); } colors.push(colors.shift()); }).on('mouseleave.compare', (e) => { const target = e.currentTarget; timeout = setTimeout(() => { leaveImage($overlay, target); }, 200); }); $(document).on('scroll.compare', (e) => { const temp = $overlay.find('img:visible')[0]; if (temp) { const $prev = $(temp.targetImage); if (!$prev.is(':hover')) { $prev.trigger('mouseleave'); $images.find('img:hover').trigger('mousenter'); } } }).on('keydown.compare', (e) => { e.preventDefault(); e.stopImmediatePropagation(); switch (e.key) { case 'Escape': exitCompare($overlay, $images); break; case 'Shift': try { const index = $images.index($overlay.find('img:visible')[0].targetImage); baseImage = $images[index]; } catch (err) { baseImage = undefined; console.warn(err); } break; case 'I': case 'i': case 'ArrowUp': try { const target = $overlay.find('img:visible')[0]; let threshold = target.threshold; if (threshold !== undefined && threshold >= 0) { const thresholdPrev = threshold; $message.text(`Threshold: ${thresholdPrev.toFixed(4)}`).css('opacity', '1'); threshold += target.step; if (threshold > 1) { threshold = 1; } target.threshold = -1; diffThem(target.baseImage[target.baseImage.src].src, target.targetImage[target.targetImage.src].src, (a, b) => { }, { alpha: 0.5, threshold: threshold }) .then((diffSrc) => { let temp; if (diffSrc === null) { target.src = text2SVGDataURL(`Sizes Not Match`, 120); temp = thresholdPrev; setTimeout(() => { target.threshold = thresholdPrev; }, 300); } else { target.src = diffSrc; temp = threshold; setTimeout(() => { target.threshold = threshold; }, 300); } $message.text(`Threshold: ${temp.toFixed(4)}`).css('opacity', '1'); setTimeout(() => $message.css('opacity', '0'), 300); }); } } catch (err) { console.warn(err); } break; case 'K': case 'k': case 'ArrowDown': try { const target = $overlay.find('img:visible')[0]; let threshold = target.threshold; if (threshold !== undefined && threshold >= 0) { const thresholdPrev = threshold; $message.text(`Threshold: ${thresholdPrev.toFixed(4)}`).css('opacity', '1'); threshold -= target.step; if (threshold < 0) { threshold = 0; } target.threshold = -1; diffThem(target.baseImage[target.baseImage.src].src, target.targetImage[target.targetImage.src].src, (a, b) => { }, { alpha: 0.5, threshold: threshold }) .then((diffSrc) => { let temp; if (diffSrc === null) { target.src = text2SVGDataURL(`Sizes Not Match`, 120); temp = thresholdPrev; setTimeout(() => { target.threshold = thresholdPrev; }, 300); } else { target.src = diffSrc; temp = threshold; setTimeout(() => { target.threshold = threshold; }, 300); } $message.text(`Threshold: ${temp.toFixed(4)}`).css('opacity', '1'); setTimeout(() => $message.css('opacity', '0'), 300); }); } } catch (err) { console.warn(err); } break; case 'J': case 'j': case 'ArrowLeft': try { const target = $overlay.find('img:visible')[0]; switch (target.step) { case 0.0001: target.step = 0.001; break; case 0.001: target.step = 0.01; break; case 0.01: target.step = 0.1; break; case 0.1: target.step = 1.0; break; default: break; } if (target.step) { $message.text(`Step: ${target.step.toFixed(4)}`).css('opacity', '1'); setTimeout(() => $message.css('opacity', '0'), 300); } } catch (err) { console.warn(err); } break; case 'L': case 'l': case 'ArrowRight': try { const target = $overlay.find('img:visible')[0]; switch (target.step) { case 1.0: target.step = 0.1; break; case 0.1: target.step = 0.01; break; case 0.01: target.step = 0.001; break; case 0.001: target.step = 0.0001; break; default: break; } if (target.step) { $message.text(`Step: ${target.step.toFixed(4)}`).css('opacity', '1'); setTimeout(() => $message.css('opacity', '0'), 300); } } catch (err) { console.warn(err); } break; case 'Q': case 'q': $overlay.css('opacity', 0.5); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': step = parseInt(e.key); break; case '0': step = 10; break; case 'E': case 'e': try { const index = $images.index($overlay.find('img:visible')[0].targetImage); $($images[index]).trigger('mouseleave'); const nextElem = $images[index + step] || $images[index]; $(nextElem).trigger('mouseenter', [e.shiftKey]); } catch (err) { console.warn(err); } break; case 'W': case 'w': try { const index = $images.index($overlay.find('img:visible')[0].targetImage); $($images[index]).trigger('mouseleave'); const nextElem = $images[index - step] || $images[index]; $(nextElem).trigger('mouseenter', [e.shiftKey]); } catch (err) { console.warn(err); } break; } return false; }).on('keyup.compare', (e) => { e.preventDefault(); e.stopImmediatePropagation(); switch (e.key) { case 'Q': case 'q': $overlay.css('opacity', ''); break; } return false; }); } // Function fired when compare button is clicked and toggled off // or quit via keyboard 'esc' function exitCompare($overlay, $images) { if (Mousetrap) { Mousetrap.unpause(); } leaveImage($overlay); $overlay.hide()[0].state = false; $images .off('mouseenter.compare') .off('mouseleave.compare'); $(document) .off('scroll.compare') .off('keydown.compare'); } // An overlay on the whole page const $overlay = $('<div/>').css({ 'position': 'fixed', 'top': 0, 'right': 0, 'bottom': 0, 'left': 0, 'z-index': 2147483646, 'background-color': 'rgba(0, 0, 0, 0.75)', 'pointer-events': 'none', 'display': 'none' }); // A message on the whole page const $message = $('<div>').css({ 'top': '50%', 'left': '50%', 'z-index': 2147483647, 'position': 'fixed', 'transform': 'translate(-50%, -50%)', 'opacity': '0', 'vertical-align': 'middle', 'pointer-events': 'none', 'transition': 'all 0.1s', 'font-size': '500%', 'color': 'yellow', 'font-weight': 'bold' }); $overlay.append($message); // The compare button const $compareButton = $(`<svg xmlns="http://www.w3.org/2000/svg"> <path id="ld" d="M20 6H10c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h10v4h4V2h-4v4zm0 30H10l10-12v12zM38 6H28v4h10v26L28 24v18h10c2.21 0 4-1.79 4-4V10c0-2.21-1.79-4-4-4z"/> </svg>`).attr({ 'width': '30', 'height': '30', 'viewBox': '0 0 48 48', 'stroke': 'white', 'stroke-width': '5px', 'fill': 'gray' }).css({ 'position': 'fixed', 'top': '15px', 'right': '15px', 'z-index': 2147483647, 'paint-order': 'stroke', 'opacity': 0, 'transition': 'all 0.2s', 'cursor': 'auto' }).on('mouseenter', (e) => { $(e.currentTarget).attr({ 'fill': 'gray' }).css({ 'opacity': 0.2 }); timeout = setTimeout(() => activateCompare($(e.currentTarget)), $overlay[0].state ? 0 : 1000); }).on('mouseleave', (e) => { clearTimeout(timeout); $(e.currentTarget).attr({ 'fill': 'gray' }).css({ 'cursor': 'auto', 'opacity': 0 })[0].state = false; }).click((e) => { if (e.currentTarget.state) { switch ($overlay[0].state) { case false: enterCompare($overlay, $('img'), $message); break; case true: exitCompare($overlay, $('img')); break; } } else { let x = e.clientX; let y = e.clientY; const lowerElement = document .elementsFromPoint(x, y) .find(e => !['svg', 'path'].includes(e.tagName)); lowerElement.click(); } }).mousedown((e) => { if (e.currentTarget.state) { $(e.currentTarget).attr({ 'fill': '#006000' }); } }).mouseup((e) => { if (e.currentTarget.state) { $(e.currentTarget).attr({ 'fill': '#008000' }); } }); $overlay[0].state = false; $compareButton[0].state = false; $('body').append($compareButton).append($overlay); })(window.$.noConflict(true), unsafeWindow.Mousetrap, window.pixelmatch, window.UPNG, unsafeWindow.URL.createObjectURL ? unsafeWindow.URL : unsafeWindow.webkitURL);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址