Civitai Post Galery

Fit-to-screen image viewer for Civitai posts

当前为 2024-08-03 提交的版本,查看 最新版本

// ==UserScript==
// @name         Civitai Post Galery
// @description  Fit-to-screen image viewer for Civitai posts
// @author       yee7doom https://civitai.com/user/yee7doom [email protected]
// @license MIT
// @version      1.0
// @grant        none
// @include      /^https://civitai\.com/posts/[0-9]+$/
// @run-at       document-idle
// @namespace https://greasyfork.org/users/1344777
// ==/UserScript==

var keyForward = "x";
var keyBack = "z";

function getWinSize() {
	var div = document.createElement('div');
	div.style.width = div.style.height = '100%';
	div.style.left = div.style.top = '0';
	div.style.position = 'fixed';
	document.body.appendChild(div);
	var s = {w: div.clientWidth, h: div.clientHeight};
	s.p = s.w*1000+s.h;
	document.body.removeChild(div);
	return s;
};

function setFullscreen() {
  // fit image to screen
  let winSize = getWinSize();
  curItem.style.maxWidth = "none";
  curItem.style.width = "auto";
  curImg.style.maxWidth = `${winSize.w}px`;
  curImg.style.maxHeight = `${winSize.h}px`;
  // hide image buttons
  curItem.style.zIndex = "12";
  curImg.style.position = "relative";
  curImg.style.zIndex = "11";
  // show image buttons on mouse hover
  curItem.addEventListener('mouseenter', setFocus);
  curItem.addEventListener('mouseleave', removeFocus);
  // scroll to the image
  curItem.scrollIntoView({behavior: 'auto', block: 'center', inline: 'center'});
};

function removeFullscreen() {
  // revert to the default image appearance
  curItem.style.maxWidth = "700px";
  curImg.style.maxWidth = "700px";
  curImg.style.maxHeight = "none";
  curItem.style.zIndex = "0";
  curImg.style.zIndex = "0";
  // remove on mouse hover listeners
  curItem.removeEventListener('mouseenter', setFocus);
  curItem.removeEventListener('mouseleave', removeFocus);
};

function setFocus() {
  if (curImg) {
    curImg.style.zIndex = "0";
  };
};

function removeFocus() {
  if (curImg) {
    curImg.style.zIndex = "11";
  };
};

function scrollPost(value) {
  // remove fullscreen from current image
  if (curItem) {
    removeFullscreen();
  };

  // find all post image links
  let postLinks = [...scroller.getElementsByTagName('a')].filter((i) => i.getAttribute("href", '').startsWith('/images/'));
  if (postLinks.length == 0) { return; };

  // define next item
  let nextPos = curPos + value;
  if (postLinks[nextPos] == undefined) {
    nextPos = value > 0 ? 0 : postLinks.length-1;
  };

  // show the image
  curPos = nextPos;
  curItem = postLinks[curPos].parentNode; // the div image container with all the buttons
  curImg = postLinks[curPos].childNodes[0]; // the actual img element
  setFullscreen();
}

var header = document.getElementsByTagName('header')[0];
var scroller = document.getElementsByTagName('main')[0].childNodes[0];
var footer = document.getElementsByTagName('footer')[0];
var curPos = -1;
var curItem = null;
var curImg = undefined;

// disable max width for the post contents
scroller.childNodes[1].childNodes[0].style.maxWidth = "none";

// remove header and footer from their fixed positions
scroller.childNodes[0].style.position = 'relative';
scroller.insertBefore(header, scroller.childNodes[0]);
scroller.appendChild(footer);

// bind the buttons
document.onkeydown = function(e) {
  switch (e.key) {
    case keyForward:
      scrollPost(1);
      break;
    case keyBack:
      scrollPost(-1);
      break;
  }
};