您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
添加了几个快捷键,前进/后退间隔修改,右侧列表悬停展开
// ==UserScript== // @name 115视频播放 快捷键 // @namespace https://greasyfork.org/zh-CN/users/1365949 // @version 1.1 // @description 添加了几个快捷键,前进/后退间隔修改,右侧列表悬停展开 // @author ewt45 // @license MIT // @match https://115vod.com/* // @match https://115.com/*mode=wangpan* // @icon https://www.google.com/s2/favicons?sz=64&domain=115.com // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // @grant GM_registerMenuCommand // ==/UserScript== (function () { 'use strict'; //按键参考 https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values#navigation_keys if (window.top !== window.self) return // 跳过iframe console.log("添加油猴脚本-115视频快捷键") const video = document.querySelector("#js-video") let currentTimeDiv = null; //用于前进/后退时显示当前时间,在addVideoKeyEventListener中初始化 let currentTimeDivTimeoutId = 0; let fastForwardTimeoutId = null; //快进的倒计时id let isFastForwarding = false let isResizing = false; // 标记是否正在拖拽 let startX; // 鼠标按下时的 X 坐标 let startWidth; // 拖拽开始时 div 的宽度 /** 监听键盘按键以实现各种快捷键 */ const addVideoKeyEventListener = () => { addCurrentTimeDiv() // 方向键右按下,如果长按则3倍速播放 document.addEventListener('keydown', (e) => { if (e.key.toLowerCase() === 'arrowright' && !fastForwardTimeoutId) { fastForwardTimeoutId = setTimeout(() => { video.playbackRate = 3.0; // 3倍速 isFastForwarding = true //左上角提示文字 currentTimeDiv.innerHTML = '3倍速播放中' currentTimeDiv.style.display = 'block'; }, 800); } }) document.addEventListener('keyup', (e) => { // console.log('松开按键 ', e.key, e.keyCode) //全屏 if (e.key.toLowerCase() === 'f') { console.log('快捷键-全屏') e.stopPropagation() const el = document.querySelector('a[rel="fullscreen"]') if (el) { el.click() //不知为何顶端的标题不会自动隐藏 setTimeout(() => { document.querySelector('[rel="full_menu"]').style.display = 'none' }, 2000) } } // k和l也是前进和后退 // else if (e.key.toLowerCase() === 'k' || e.key.toLowerCase() === 'l') { // const isForward = e.key.toLowerCase() === 'l'; //是否为快进 // const interval = getInterval() // const video = document.querySelector("#js-video") // const playBtn = document.querySelector('[btn="play"]') // const duration = ~~(video.duration || 0) // const currentTime = ~~(video.currentTime || 0) // console.log('快捷键-' + (isForward ? "快进" : "快退"), (isForward ? "是否符合条件" + (currentTime + interval < duration) : "")) // if (!duration) // return // // if (video.paused && playBtn) // // playBtn.click() // //调整视频进度 // if (isForward && (currentTime + interval < duration)) { // video.currentTime += interval; // } else if (!isForward && (currentTime - interval > 0)) { // video.currentTime -= interval; // } // //左上角显示当前进度 // const percent = video.currentTime / video.duration * 10000; // currentTimeDiv.innerHTML = oofUtil.date.numFormat(video.currentTime * 1000, 'hh:mm:ss') || '00:00:00' + ' (' + (~~percent) / 100 + '%)'; // currentTimeDiv.style.display = 'block'; // if (currentTimeDivTimeoutId) // clearTimeout(currentTimeDivTimeoutId); // currentTimeDivTimeoutId = setTimeout(() => { currentTimeDiv.style.display = 'none' }, 3000) // } //方向键左右 //有问题,后退会转一会圈然后播放,控制台有个报错。前进无效。 else if (e.key.toLowerCase() === 'arrowleft' || e.key.toLowerCase() === 'arrowright') { if (!(video instanceof HTMLVideoElement) || !(currentTimeDiv instanceof HTMLElement)) return e.stopPropagation() //阻止原代码中的事件监听(原监听在window上) const isForward = e.key.toLowerCase() === 'arrowright' const interval = getInterval() * (isForward ? 1 : -1) const duration = ~~(video.duration || 0) console.log('快捷键-前进/后退') // 清除长按计时器 clearTimeout(fastForwardTimeoutId) fastForwardTimeoutId = null // 如果是快进播放,则停止倍速并直接返回 if (isFastForwarding) { video.playbackRate = 1.0 isFastForwarding = false currentTimeDiv.style.display = 'none' return } // if (video.paused && playBtn) // playBtn.click() //调整视频进度 video.currentTime += interval; //左上角显示当前进度 const percent = video.currentTime / video.duration * 10000; currentTimeDiv.innerHTML = (oofUtil.date.numFormat(video.currentTime * 1000, 'hh:mm:ss') || '00:00:00') + ' (' + (~~percent) / 100 + '%)'; currentTimeDiv.style.display = 'block'; if (currentTimeDivTimeoutId) clearTimeout(currentTimeDivTimeoutId); currentTimeDivTimeoutId = setTimeout(() => { currentTimeDiv.style.display = 'none' }, 3000) } }, true); } /** 显示设置弹窗 */ function createSettingsDialog() { if (document.getElementById('sh-dialog')) return // 创建弹窗元素 const frame = document.createElement('div'); frame.innerHTML = ` <div id="sh-dialog" style="position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 20px; background-color: white; border: 1px solid black; z-index: 10000; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 10px; text-align: center;"> <div style="display:table;"> <div style="display:table-cell;">前进/后退 时间间隔(秒) </div> <div style="display:table-cell; padding-left:20px;"> <input id="sh-interval" type="number" required/> </div> </div> <div style="text-align: left; margin-top:20px; max-height:200px; overflow: auto;">快捷键: <br>前进/后退: 方向键右/左 <br>快进(3倍速): 方向键右长按 <br>全屏: F <br><br>官方自带的快捷键: <br>m=静音 <br>w=网页全屏 <br>esc=退出全屏 <br>空格,k=播放/暂停 <br>j=倒退10秒 <br>l=前进10秒 <br>0-9=跳转到进度0%-100% <br>上=音量+10% <br>下=音量-10% <br>c=隐藏/开启字幕 <br>n=下一个 <br>p=上一个 <br>end=最后一个 <br>home=第一个 </div> <button style="margin-top:20px" id="sh-closebtn">保存</button> </div> `; document.body.appendChild(frame); document.getElementById('sh-interval').value = getInterval() document.getElementById('sh-closebtn').addEventListener('click', function () { setInterval(parseInt(document.getElementById('sh-interval').value)) document.body.removeChild(frame); }); } /** 初次启动时添加左上角的时间显示div */ const addCurrentTimeDiv = () => { let box = document.querySelector('#js-video_box'); if (!box || currentTimeDiv) return const root = document.createElement('div'); root.innerHTML = '<div id="currentTimeDiv" style="position:absolute;left:20px;top:20px;font-size:14px;z-index:3;color:#fff;"></div>' box.appendChild(root) currentTimeDiv = document.getElementById("currentTimeDiv") } /** 主界面左侧栏宽度可拖拽 */ const createDragbar = () => { const leftContainer = document.getElementById("site_left_bar") const rightContainer = document.querySelector(".main-hflow.main-scrollbox") let dragbar = document.getElementById("left_container_drag_bar") if (!leftContainer || !rightContainer || dragbar) return leftContainer.style.width = readLeftContainerWidth() + 'px'; dragbar = document.createElement('div') dragbar.id = "left_container_drag_bar" dragbar.style.width = '10px' dragbar.style.position = 'absolute' dragbar.style.top = 0 dragbar.style.right = 0 dragbar.style.bottom = 0 dragbar.style.cursor = 'ew-resize' // dragbar.style.backgroundColor = 'black' leftContainer.appendChild(dragbar) dragbar.addEventListener('mousedown', (e) => { isResizing = true; startX = e.clientX; startWidth = leftContainer.offsetWidth; // 记录 div 的当前宽度 (包含 padding 和 border) e.preventDefault(); // 阻止默认的拖拽行为 leftContainer.style.pointerEvents = 'none' rightContainer.style.pointerEvents = 'none' // 防止鼠标进入文件列表后 显示操作栏 拖拽被打断 }); document.addEventListener('mousemove', (e) => { if (!isResizing) return; // 如果没有在拖拽,则不执行任何操作 const newWidth = startWidth + e.clientX - startX; leftContainer.style.width = `${Math.max(100, newWidth)}px`; }); document.addEventListener('mouseup', () => { isResizing = false; // 停止拖拽 leftContainer.style.pointerEvents = '' rightContainer.style.pointerEvents = '' saveLeftContainerWidth(leftContainer.offsetWidth) }); } const setInterval = (value) => { if (!value || value <= 0) value = 5; GM_setValue("interval", value) } /** 获取前进/后退的时间间隔,默认5秒 */ const getInterval = () => { return GM_getValue("interval", 5) } const saveLeftContainerWidth = (value) => GM_setValue("leftContainerWidth", value) const readLeftContainerWidth = () => GM_getValue("leftContainerWidth", 340) // 视频播放 if (window.location.href.startsWith("https://115vod.com/")) { // 按键监听 addVideoKeyEventListener() // 右侧列表 悬停展开 const expandListBtn = document.getElementById("js_pl_control_expand") if (expandListBtn) { expandListBtn.addEventListener('mouseover', (e) => { expandListBtn.classList.contains('vpls-open') && expandListBtn.click() }) //仅在未打开列表时点击。 expandListBtn.parentElement.parentElement.addEventListener('mouseleave', (e) => { expandListBtn.classList.contains('vpls-close') && expandListBtn.click() }) //仅在已打开时点击 } } // 文件页面 if (window.location.href.startsWith("https://115.com/?")) { GM_addStyle(` .sub-hflow-file {width: auto;} .bar-info {flex-wrap: wrap;} .file-module-allfile .title {flex-wrap: wrap;} .file-module-allfile .title .name {flex: 1 0 auto; white-space: nowrap;}`); createDragbar() } // 油猴插件处的设置 GM_registerMenuCommand('设置', createSettingsDialog); })();