// ==UserScript==
// @name Pixiv Previewer
// @namespace https://github.com/lintmx
// @version 0.0.1
// @description preview image in pixiv.
// @author lintmx
// @license MIT
// @match https://www.pixiv.net*
// @grant none
// @run-at document-idle
// ==/UserScript==
const isDev = false;
const Logger = {
debug: (...msg) => isDev && console.log('[Pixiv Previewer]', 'DEBUG:', ...msg),
info: (...msg) => console.log('[Pixiv Previewer]', 'INFO:', ...msg),
error: (...msg) => console.log('[Pixiv Previewer]', 'ERROR:', ...msg),
};
const Icon = {
Expand:
'data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgZGF0YS1wcmVmaXg9ImZhcyIgZGF0YS1pY29uPSJleHBhbmQtYWx0IiBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtZXhwYW5kLWFsdCBmYS13LTE0IiByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGZpbGw9ImN1cnJlbnRDb2xvciIgZD0iTTIxMi42ODYgMzE1LjMxNEwxMjAgNDA4bDMyLjkyMiAzMS4wMjljMTUuMTIgMTUuMTIgNC40MTIgNDAuOTcxLTE2Ljk3IDQwLjk3MWgtMTEyQzEwLjY5NyA0ODAgMCA0NjkuMjU1IDAgNDU2VjM0NGMwLTIxLjM4MiAyNS44MDMtMzIuMDkgNDAuOTIyLTE2Ljk3MUw3MiAzNjBsOTIuNjg2LTkyLjY4NmM2LjI0OC02LjI0OCAxNi4zNzktNi4yNDggMjIuNjI3IDBsMjUuMzczIDI1LjM3M2M2LjI0OSA2LjI0OCA2LjI0OSAxNi4zNzggMCAyMi42Mjd6bTIyLjYyOC0xMTguNjI4TDMyOCAxMDRsLTMyLjkyMi0zMS4wMjlDMjc5Ljk1OCA1Ny44NTEgMjkwLjY2NiAzMiAzMTIuMDQ4IDMyaDExMkM0MzcuMzAzIDMyIDQ0OCA0Mi43NDUgNDQ4IDU2djExMmMwIDIxLjM4Mi0yNS44MDMgMzIuMDktNDAuOTIyIDE2Ljk3MUwzNzYgMTUybC05Mi42ODYgOTIuNjg2Yy02LjI0OCA2LjI0OC0xNi4zNzkgNi4yNDgtMjIuNjI3IDBsLTI1LjM3My0yNS4zNzNjLTYuMjQ5LTYuMjQ4LTYuMjQ5LTE2LjM3OCAwLTIyLjYyN3oiPjwvcGF0aD48L3N2Zz4=',
Redirect:
'data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgZGF0YS1wcmVmaXg9ImZhcyIgZGF0YS1pY29uPSJsb2NhdGlvbi1hcnJvdyIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWxvY2F0aW9uLWFycm93IGZhLXctMTYiIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHBhdGggZmlsbD0iY3VycmVudENvbG9yIiBkPSJNNDQ0LjUyIDMuNTJMMjguNzQgMTk1LjQyYy00Ny45NyAyMi4zOS0zMS45OCA5Mi43NSAxOS4xOSA5Mi43NWgxNzUuOTF2MTc1LjkxYzAgNTEuMTcgNzAuMzYgNjcuMTcgOTIuNzUgMTkuMTlsMTkxLjktNDE1Ljc4YzE1Ljk5LTM4LjM5LTI1LjU5LTc5Ljk3LTYzLjk3LTYzLjk3eiI+PC9wYXRoPjwvc3ZnPg==',
};
const Previewer = {
addButton: () => {
Logger.debug('Start Add Button');
const illustList = document.querySelectorAll('div[type=illust]>div:not(.pixiv-previewer-btn-exist)');
for (const illust of illustList) {
const previewButton = document.createElement('div');
previewButton.className = 'pixiv-previewer-view-btn';
previewButton.style.cssText = [
'position: absolute',
'left: 0px',
'bottom: 0px',
'width: 32px',
'height: 32px',
'cursor: pointer',
'background: no-repeat center/50%',
'background-image: url("' + Icon.Expand + '")',
].join(';');
previewButton.innerHTML = ' ';
previewButton.addEventListener('click', (e) => {
const clickImgElm = e.target.parentNode.querySelector('a>div:last-child>img');
const pageSizeElm = e.target.parentNode.querySelector(
'a>div:first-child>div:last-child>div>span:last-child'
);
if (!clickImgElm) return;
const imgUrl = clickImgElm.src;
const pageSize = pageSizeElm ? pageSizeElm.innerText : '1';
Previewer.showPreview(imgUrl, pageSize);
});
illust.appendChild(previewButton);
illust.classList.add('pixiv-previewer-btn-exist');
}
},
showPreview: (url, pageSize = 1) => {
const { Time, IllustId } = Previewer.convert(url);
const Cover = document.querySelector('#pixiv-previewer-cover');
Cover.style.display = 'flex';
Cover.dataset.time = Time;
Cover.dataset.id = IllustId;
Cover.dataset.size = pageSize;
Cover.dataset.page = 0;
document.querySelector('#pixiv-previewer-redirect').href = 'https://www.pixiv.net/artworks/' + IllustId;
document.querySelector(
'#pixiv-previewer-image'
).src = `https://i.pximg.net/img-master/img/${Time}/${IllustId}_p0_master1200.jpg`;
},
convert: (baseUrl = '') => {
const [, Time = '', IllustId = ''] = baseUrl.match(
/^https:\/\/i\.pximg\.net\/.+?\/img\/([0-9\/]+?)\/(\d+?)_p.+?\.[a-z]+$/
);
return { Time, IllustId };
},
};
(function () {
('use strict');
Logger.debug('Script Start.');
const rootElm = document.querySelector('#root');
// 全屏预览遮罩
const previewCover = document.createElement('div');
previewCover.id = 'pixiv-previewer-cover';
previewCover.style.cssText = [
'z-index: 445',
'width: 100%',
'height: 100%',
'position: fixed',
'left: 0px',
'right: 0px',
'top: 0px',
'bottom: 0px',
'display: none',
'justify-content: center',
'align-items: center',
'flex-direction: column',
'background: rgba(0, 0, 0, 0.6)',
].join(';');
previewCover.addEventListener('click', (e) => {
Logger.debug('cover click.');
e.target.style.display = 'none';
});
const previewRedirect = document.createElement('a');
previewRedirect.id = 'pixiv-previewer-redirect';
previewRedirect.style.cssText = [
'width: 32px',
'height: 32px',
'background: red',
'margin-top: 16px',
'display: block',
'background: no-repeat center',
'background-image: url("' + Icon.Redirect + '")',
].join(';');
previewCover.appendChild(previewRedirect);
const previewImage = document.createElement('img');
previewImage.id = 'pixiv-previewer-image';
previewImage.style.cssText = ['max-width: 90%', 'max-height: 90%', 'margin: auto'].join(';');
previewImage.addEventListener('click', (e) => {
e.stopPropagation();
const Cover = document.querySelector('#pixiv-previewer-cover');
const { time, id, size } = Cover.dataset;
let { page = 0 } = Cover.dataset;
let next = Number.parseInt(page, 10) + 1;
if (next + 1 > size) {
next = 0;
}
if (next != page) {
document.querySelector(
'#pixiv-previewer-image'
).src = `https://i.pximg.net/img-master/img/${time}/${id}_p${next}_master1200.jpg`;
Cover.dataset.page = next;
}
Logger.debug('click image');
});
previewCover.appendChild(previewImage);
rootElm.appendChild(previewCover);
setInterval(Previewer.addButton, 1000);
Logger.debug('Script End.');
})();