showOwoBig(target: Node) { const RATIO = 2; const MaxLength = 200; const body = document.querySelector('body') || document.createElement('body'); let div = document.querySelector('#owo-big') as HTMLElement;
if (!div) { div = document.createElement('div'); div.id = 'owo-big'; body.appendChild(div); }
const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { const element = node as HTMLElement;
if (shouldEnlarge(element)) { setupHoverEffects(element); } }); }); });
observer.observe(target, { subtree: true, childList: true });
function shouldEnlarge(element: HTMLElement): boolean { const classList = element.classList; const attributes = element.attributes; const querySelector = element.querySelector;
return classList?.contains('atk-grp') || classList?.contains('atk-comment-wrap') || attributes?.getNamedItem('atk-emoticon') !== null || querySelector?.('img[atk-emoticon]') !== null; }
function setupHoverEffects(element: HTMLElement) { let flag = true; let owoTime: number; element.addEventListener('pointerover', (e: PointerEvent) => { if (e.pointerType !== 'mouse') return;
const imgElement = e.target as HTMLImageElement; if (flag && imgElement.tagName === 'IMG' && imgElement.hasAttribute('atk-emoticon')) { flag = false; owoTime = window.setTimeout(() => { const alt = imgElement.getAttribute("notitle") === "true" ? '' : imgElement.alt || ''; const { clientHeight, clientWidth, naturalHeight, naturalWidth } = imgElement;
if (clientHeight <= MaxLength && clientWidth <= MaxLength) { const { tempWidth, tempHeight } = calculateSize(clientHeight, clientWidth, naturalHeight, naturalWidth, RATIO, MaxLength); const { top, left } = calculatePosition(e, tempWidth, clientWidth, body);
div.style.cssText = ` display: block; width: ${tempWidth + 32}px; // div padding: 16px; left: ${left}px; top: ${top}px; `; div.innerHTML = ` <img src="${imgElement.src}" style="height: ${tempHeight}px;width: ${tempWidth}px" onerror="this.classList.add('error')"> <p>${alt.trim().replace(/\s+/g, ' ').replace(/ /g, '<br>')}</p> `; } }, 300); } });
element.addEventListener('pointerout', () => { flag = true; div.style.display = 'none'; clearTimeout(owoTime); }); }
function calculateSize( clientHeight: number, clientWidth: number, naturalHeight: number, naturalWidth: number, ratio: number, maxLength: number ): { tempWidth: number, tempHeight: number } { const zoomHeight = clientHeight * ratio; const zoomWidth = clientWidth * ratio; const constrainedHeight = Math.min(zoomHeight, maxLength, Math.max(clientHeight, naturalHeight)); const constrainedWidth = Math.min(zoomWidth, maxLength, Math.max(clientWidth, naturalWidth)); const aspectRatio = constrainedWidth / constrainedHeight; const tempWidth = aspectRatio >= 1 ? Math.min(constrainedWidth, maxLength) : Math.min((constrainedWidth * maxLength) / constrainedHeight, constrainedWidth); const tempHeight = aspectRatio < 1 ? Math.min(constrainedHeight, maxLength) : Math.min((constrainedHeight * maxLength) / constrainedWidth, constrainedHeight); return { tempWidth, tempHeight }; }
function calculatePosition( e: MouseEvent, tempWidth: number, clientWidth: number, bodyElement: HTMLElement ): { top: number, left: number } { const top = e.clientY - e.offsetY; let left = e.clientX - e.offsetX - (tempWidth - clientWidth) / 2; left = Math.max(10, Math.min(left, bodyElement.clientWidth - tempWidth - 10)); return { top, left }; } }
|