您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button that opens a fullscreen grid of high-res photos. Clicking a photo opens a carousel overlay that scales the image to fit without cropping. In the carousel, a "Grid View" button lets you return to the grid.
// ==UserScript== // @name PerfectGonzo: View Photos Popup & Carousel (High Res, Fit Entire Image, Grid Toggle) // @namespace http://tampermonkey.net/ // @version 1.7 // @description Adds a button that opens a fullscreen grid of high-res photos. Clicking a photo opens a carousel overlay that scales the image to fit without cropping. In the carousel, a "Grid View" button lets you return to the grid. // @match *://*.perfectgonzo.com/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Function to create the grid popup gallery function createPopupGallery(imageUrls) { // Create overlay for grid gallery const overlay = document.createElement('div'); overlay.id = 'pgPhotoOverlay'; overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.9)'; overlay.style.zIndex = '10000'; overlay.style.overflowY = 'auto'; overlay.style.padding = '20px'; // Close button for grid gallery const closeBtn = document.createElement('button'); closeBtn.innerText = 'X'; closeBtn.style.position = 'fixed'; closeBtn.style.top = '20px'; closeBtn.style.right = '20px'; closeBtn.style.fontSize = '24px'; closeBtn.style.background = 'transparent'; closeBtn.style.color = '#fff'; closeBtn.style.border = 'none'; closeBtn.style.cursor = 'pointer'; closeBtn.style.zIndex = '10001'; overlay.appendChild(closeBtn); closeBtn.addEventListener('click', function() { document.body.removeChild(overlay); }); // Gallery container (grid layout) const galleryContainer = document.createElement('div'); galleryContainer.style.display = 'flex'; galleryContainer.style.flexWrap = 'wrap'; galleryContainer.style.justifyContent = 'center'; galleryContainer.style.gap = '20px'; galleryContainer.style.marginTop = '60px'; // leave room for the close button overlay.appendChild(galleryContainer); imageUrls.forEach((url, index) => { const imgContainer = document.createElement('div'); imgContainer.style.flex = '1 1 auto'; imgContainer.style.maxWidth = '400px'; imgContainer.style.cursor = 'pointer'; const img = document.createElement('img'); img.src = url; img.alt = 'Photo'; img.style.width = '100%'; img.style.height = 'auto'; img.style.border = '2px solid #fff'; img.style.boxShadow = '0 0 10px rgba(255,255,255,0.5)'; img.style.transition = 'transform 0.2s ease-in-out'; img.addEventListener('mouseover', () => { img.style.transform = 'scale(1.05)'; }); img.addEventListener('mouseout', () => { img.style.transform = 'scale(1)'; }); // When clicking the image, close the grid and open the carousel at this index. img.addEventListener('click', function(e) { e.stopPropagation(); document.body.removeChild(overlay); createCarousel(index, imageUrls); }); imgContainer.appendChild(img); galleryContainer.appendChild(imgContainer); }); document.body.appendChild(overlay); } // Function to create a fullscreen carousel overlay with a "Grid View" button function createCarousel(currentIndex, imageUrls) { // Create carousel overlay const carouselOverlay = document.createElement('div'); carouselOverlay.id = 'pgCarouselOverlay'; carouselOverlay.style.position = 'fixed'; carouselOverlay.style.top = '0'; carouselOverlay.style.left = '0'; carouselOverlay.style.width = '100vw'; carouselOverlay.style.height = '100vh'; carouselOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.9)'; carouselOverlay.style.zIndex = '10001'; carouselOverlay.style.display = 'flex'; carouselOverlay.style.alignItems = 'center'; carouselOverlay.style.justifyContent = 'center'; // Container for image and controls const container = document.createElement('div'); container.style.position = 'relative'; container.style.width = '100vw'; container.style.height = '100vh'; container.style.display = 'flex'; container.style.alignItems = 'center'; container.style.justifyContent = 'center'; carouselOverlay.appendChild(container); // Image element with scaling that preserves aspect ratio const carouselImg = document.createElement('img'); carouselImg.src = imageUrls[currentIndex]; carouselImg.style.display = 'block'; carouselImg.style.maxWidth = '100%'; carouselImg.style.maxHeight = '100%'; carouselImg.style.width = 'auto'; carouselImg.style.height = 'auto'; carouselImg.style.objectFit = 'contain'; container.appendChild(carouselImg); // Left arrow const leftArrow = document.createElement('div'); leftArrow.innerHTML = '❮'; // left arrow symbol leftArrow.style.position = 'absolute'; leftArrow.style.left = '20px'; leftArrow.style.top = '50%'; leftArrow.style.transform = 'translateY(-50%)'; leftArrow.style.fontSize = '48px'; leftArrow.style.color = '#fff'; leftArrow.style.cursor = 'pointer'; leftArrow.style.userSelect = 'none'; container.appendChild(leftArrow); // Right arrow const rightArrow = document.createElement('div'); rightArrow.innerHTML = '❯'; // right arrow symbol rightArrow.style.position = 'absolute'; rightArrow.style.right = '20px'; rightArrow.style.top = '50%'; rightArrow.style.transform = 'translateY(-50%)'; rightArrow.style.fontSize = '48px'; rightArrow.style.color = '#fff'; rightArrow.style.cursor = 'pointer'; rightArrow.style.userSelect = 'none'; container.appendChild(rightArrow); // Close button const closeBtn = document.createElement('div'); closeBtn.innerHTML = '×'; closeBtn.style.position = 'absolute'; closeBtn.style.top = '20px'; closeBtn.style.right = '30px'; closeBtn.style.fontSize = '48px'; closeBtn.style.color = '#fff'; closeBtn.style.cursor = 'pointer'; closeBtn.style.userSelect = 'none'; container.appendChild(closeBtn); // New: "Grid View" button to go back to grid overlay. const gridViewBtn = document.createElement('button'); gridViewBtn.innerText = 'Grid View'; gridViewBtn.style.position = 'absolute'; gridViewBtn.style.top = '20px'; gridViewBtn.style.left = '30px'; gridViewBtn.style.fontSize = '16px'; gridViewBtn.style.padding = '8px 12px'; gridViewBtn.style.background = '#ffa700'; gridViewBtn.style.border = 'none'; gridViewBtn.style.borderRadius = '5px'; gridViewBtn.style.cursor = 'pointer'; gridViewBtn.style.zIndex = '10002'; container.appendChild(gridViewBtn); // Arrow navigation events leftArrow.addEventListener('click', function(e) { e.stopPropagation(); currentIndex = (currentIndex - 1 + imageUrls.length) % imageUrls.length; carouselImg.src = imageUrls[currentIndex]; }); rightArrow.addEventListener('click', function(e) { e.stopPropagation(); currentIndex = (currentIndex + 1) % imageUrls.length; carouselImg.src = imageUrls[currentIndex]; }); // Close carousel events closeBtn.addEventListener('click', function() { document.body.removeChild(carouselOverlay); }); carouselOverlay.addEventListener('click', function(e) { if (e.target === carouselOverlay) { document.body.removeChild(carouselOverlay); } }); // "Grid View" button: remove carousel and reopen grid overlay gridViewBtn.addEventListener('click', function(e) { e.stopPropagation(); document.body.removeChild(carouselOverlay); createPopupGallery(imageUrls); }); document.body.appendChild(carouselOverlay); } // When the page loads, add the "View Photos" button window.addEventListener('load', function() { const btn = document.createElement('button'); btn.innerText = 'View Photos'; btn.style.position = 'fixed'; btn.style.top = '10px'; btn.style.right = '10px'; btn.style.zIndex = '9999'; btn.style.padding = '10px 15px'; btn.style.background = '#ffa700'; btn.style.border = 'none'; btn.style.borderRadius = '5px'; btn.style.cursor = 'pointer'; btn.style.fontSize = '14px'; document.body.appendChild(btn); // On button click, gather high-res photo URLs from the Photos section btn.addEventListener('click', function() { let imageUrls = []; const photoAnchors = document.querySelectorAll('.bxslider_pics_fancybox a[href]'); photoAnchors.forEach(anchor => { const url = anchor.href; if(url) { imageUrls.push(url); } }); imageUrls = [...new Set(imageUrls)]; // Remove duplicates if(imageUrls.length > 0) { createPopupGallery(imageUrls); } else { alert('No photos found.'); } }); }); })();