用腳本插件將NicoNico標題與上傳者移到影片上方
又用AI產了個腳本
因為上次那個自動連續播放分頁的腳本
最近刷曲改另外開個視窗 用Powertoys的always-on-top的功能
把那個視窗變成類似Picture-in-Picture的方式浮在右下角
但由於nico網頁佈局的關係 這樣基本上只看得到影片的左上角
我就想把標題跟上傳者移上來讓我能一眼看到
同時我也能直接用滑鼠手勢關閉分頁以切歌
感覺這個可能比較沒人用得到
但反正弄出來了就分享
一樣AI做的code使用就自己評估
話不多說 上code
// ==UserScript==
// @name NicoVideo - Title Above Player (Flow Correct)
// @namespace https://tampermonkey.net/
// @version 1.3.0
// @description Move existing title block so that player is below it (normal flow, no overlay, SPA-safe)
// @match https://www.nicovideo.jp/watch/*
// @match https://nicovideo.jp/watch/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(() => {
'use strict';
const MOVED_FLAG = 'data-nico-title-moved';
/* ---------- finders ---------- */
function findVideo() {
return document.querySelector('video[data-name="video-content"]');
}
// 播放器本體 container(只用來定位,不插在裡面)
function findPlayerContainer(video) {
let el = video?.parentElement;
while (el) {
if (el.tagName === 'DIV' && el.classList.contains('pos_relative')) {
return el;
}
el = el.parentElement;
}
return null;
}
// 播放器「外層文流容器」(安全插入點)
function findFlowWrapper(playerContainer) {
let el = playerContainer?.parentElement;
while (el) {
if (el.tagName === 'DIV') {
// 避開會是 absolute / overlay 的層
const style = getComputedStyle(el);
if (style.position === 'static' || style.position === 'relative') {
return el;
}
}
el = el.parentElement;
}
return null;
}
function findTitleBlock() {
const tokens = [
'd_flex',
'jc_space-between',
'ai_flex-start',
'w_100%',
'gap_var(--watch-video-information-gap)',
];
for (const div of document.querySelectorAll('div')) {
const cls = div.classList;
if (cls && tokens.every(t => cls.contains(t))) {
return div;
}
}
return null;
}
/* ---------- core ---------- */
function moveOnceReady() {
const title = findTitleBlock();
const video = findVideo();
if (!title || !video) return;
const playerContainer = findPlayerContainer(video);
if (!playerContainer) return;
const flowWrapper = findFlowWrapper(playerContainer);
if (!flowWrapper) return;
// 已正確放置就不再動
if (
title.getAttribute(MOVED_FLAG) === '1' &&
title.nextElementSibling === playerContainer
) {
return;
}
// 移到播放器「前面」(同層文流)
flowWrapper.insertBefore(title, playerContainer);
title.setAttribute(MOVED_FLAG, '1');
}
/* ---------- SPA observer ---------- */
const observer = new MutationObserver(() => {
moveOnceReady();
});
function start() {
if (!document.body) {
setTimeout(start, 200);
return;
}
observer.observe(document.body, {
childList: true,
subtree: true,
});
moveOnceReady();
}
start();
})();


留言
張貼留言