您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
为指定视频添加可移动的进度条、音量控制器、重新加载按钮和悬浮窗功能
当前为
- // ==UserScript==
- // @name Video Control with Reload and Floating Window
- // @namespace http://tampermonkey.net/
- // @version 1.3
- // @description 为指定视频添加可移动的进度条、音量控制器、重新加载按钮和悬浮窗功能
- // @match https://app.kosmi.io/*
- // @grant none
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- let videoElement = null;
- let controller = null;
- let isDragging = false;
- let initialX = 0,
- initialY = 0;
- let lastX = 0,
- lastY = 0;
- let buttonCreated = false;
- let floatingWindow = null;
- function createController() {
- controller = document.createElement('div');
- controller.id = 'video-controller';
- controller.style.cssText = `
- position: fixed;
- bottom: 20px;
- left: 50%;
- transform: translateX(-50%);
- background-color: rgba(0, 0, 0, 0.7);
- color: white;
- padding: 10px;
- border-radius: 5px;
- z-index: 9999;
- cursor: move;
- user-select: none;
- width: 300px;
- transition: width 0.3s, height 0.3s;
- display: none;
- `;
- controller.innerHTML = `
- <div id="progress-container" style="width: 100%; height: 10px; background-color: #444; position: relative; cursor: pointer;">
- <div id="progress-indicator" style="width: 0%; height: 100%; background-color: #fff; position: absolute;"></div>
- </div>
- <div id="time-display" style="text-align: center; margin-top: 5px;">0:00 / 0:00</div>
- <div id="volume-container" style="display: flex; align-items: center; margin-top: 10px;">
- <span id="volume-icon" style="margin-right: 10px;">🔊</span>
- <input type="range" id="volume-slider" min="0" max="1" step="0.1" value="1" style="flex-grow: 1;">
- </div>
- <button id="reload-button" style="width: 100%; margin-top: 10px; padding: 5px; background-color: #4CAF50; border: none; color: white; cursor: pointer;">重新加载视频控制</button>
- <button id="float-video-button" style="width: 100%; margin-top: 10px; padding: 5px; background-color: #2196F3; border: none; color: white; cursor: pointer;">创建悬浮视频窗口</button>
- <div style="display: flex; justify-content: space-between; margin-top: 10px;">
- <button class="size-button" data-action="increase-width">宽度+</button>
- <button class="size-button" data-action="decrease-width">宽度-</button>
- <button class="size-button" data-action="increase-height">高度+</button>
- <button class="size-button" data-action="decrease-height">高度-</button>
- </div>
- `;
- document.body.appendChild(controller);
- return controller;
- }
- function createToggleButton() {
- if (!buttonCreated) {
- const button = document.createElement('button');
- button.textContent = '🎥';
- button.style.cssText = `
- position: fixed;
- left: 10px;
- top: 50%;
- transform: translateY(-50%);
- padding: 5px;
- font-size: 20px;
- background-color: rgba(0, 0, 0, 0.5);
- color: white;
- border: none;
- border-radius: 50%;
- cursor: move;
- z-index: 9999;
- `;
- document.body.appendChild(button);
- let pos1 = 0,
- pos2 = 0;
- button.onmousedown = function(e) {
- e.preventDefault();
- isDragging = true;
- initialX = e.clientX;
- initialY = e.clientY;
- lastX = initialX;
- lastY = initialY;
- document.onmouseup = closeDragElement;
- document.onmousemove = throttle(buttonDrag, 16);
- };
- function buttonDrag(e) {
- if (!isDragging) return;
- e.preventDefault();
- pos1 = lastX - e.clientX;
- pos2 = lastY - e.clientY;
- lastX = e.clientX;
- lastY = e.clientY;
- button.style.top = (button.offsetTop - pos2) + "px";
- button.style.left = (button.offsetLeft - pos1) + "px";
- }
- function closeDragElement() {
- document.onmouseup = null;
- document.onmousemove = null;
- isDragging = false;
- }
- button.addEventListener('click', function() {
- if (controller.style.display === 'none') {
- controller.style.display = 'block';
- } else {
- controller.style.display = 'none';
- }
- });
- let isClicking = false;
- button.addEventListener('touchstart', function(e) {
- e.preventDefault();
- if (e.touches.length === 1) {
- isClicking = true;
- setTimeout(() => {
- if (isClicking) {
- if (controller.style.display === 'none' || controller.style.display === '') {
- controller.style.display = 'block';
- } else {
- controller.style.display = 'none';
- }
- }
- }, 200);
- } else {
- isClicking = false;
- }
- const touch = e.touches[0];
- initialX = touch.clientX - button.offsetLeft;
- initialY = touch.clientY - button.offsetTop;
- isDragging = true;
- });
- button.addEventListener('touchmove', function(e) {
- e.preventDefault();
- if (!isDragging) return;
- isClicking = false;
- const touch = e.touches[0];
- const newX = touch.clientX - initialX;
- const newY = touch.clientY - initialY;
- button.style.left = newX + 'px';
- button.style.top = newY + 'px';
- });
- button.addEventListener('touchend', function() {
- isDragging = false;
- });
- }
- buttonCreated = true;
- }
- function makeDraggable(element) {
- let pos1 = 0,
- pos2 = 0;
- element.onmousedown = dragMouseDown;
- function dragMouseDown(e) {
- if (e.target.id === 'progress-container' || e.target.id === 'progress-indicator' || e.target.id === 'volume-slider' || e.target.tagName === 'BUTTON') return;
- e.preventDefault();
- isDragging = true;
- initialX = e.clientX;
- initialY = e.clientY;
- lastX = initialX;
- lastY = initialY;
- document.onmouseup = closeDragElement;
- document.onmousemove = throttle(elementDrag, 16);
- }
- function elementDrag(e) {
- if (!isDragging) return;
- e.preventDefault();
- pos1 = initialX - e.clientX;
- pos2 = initialY - e.clientY;
- initialX = e.clientX;
- initialY = e.clientY;
- requestAnimationFrame(() => {
- element.style.top = (element.offsetTop - pos2) + "px";
- element.style.left = (element.offsetLeft - pos1) + "px";
- element.style.bottom = 'auto';
- });
- }
- function closeDragElement() {
- document.onmouseup = null;
- document.onmousemove = null;
- isDragging = false;
- }
- }
- function throttle(func, limit) {
- let lastFunc;
- let lastRan;
- return function() {
- const context = this;
- const args = arguments;
- if (!lastRan) {
- func.apply(context, args);
- lastRan = Date.now();
- } else {
- clearTimeout(lastFunc);
- lastFunc = setTimeout(function() {
- if ((Date.now() - lastRan) >= limit) {
- func.apply(context, args);
- lastRan = Date.now();
- }
- }, limit - (Date.now() - lastRan));
- }
- };
- }
- function formatTime(seconds) {
- const minutes = Math.floor(seconds / 60);
- seconds = Math.floor(seconds % 60);
- return `${minutes}:${seconds.toString().padStart(2, '0')}`;
- }
- function createFloatingWindow() {
- if (floatingWindow) {
- floatingWindow.remove();
- }
- floatingWindow = document.createElement('div');
- floatingWindow.style.cssText = `
- position: fixed;
- top: 50px;
- left: 50px;
- width: 320px;
- height: 240px;
- background-color: #000;
- border: 2px solid #fff;
- z-index: 10000;
- resize: both;
- overflow: hidden;
- `;
- const closeButton = document.createElement('button');
- closeButton.textContent = 'X';
- closeButton.style.cssText = `
- position: absolute;
- top: 5px;
- right: 5px;
- background-color: red;
- color: white;
- border: none;
- cursor: pointer;
- z-index: 10001;
- `;
- closeButton.onclick = () => floatingWindow.remove();
- floatingWindow.appendChild(closeButton);
- document.body.appendChild(floatingWindow);
- videoElement = document.querySelector('video[src^="blob:"]');
- if (videoElement) {
- // 保存视频的原始尺寸
- const originalWidth = videoElement.offsetWidth;
- const originalHeight = videoElement.offsetHeight;
- // 调整视频大小以适应悬浮窗
- videoElement.style.width = '100%';
- videoElement.style.height = '100%';
- // 将视频添加到悬浮窗中
- floatingWindow.appendChild(videoElement);
- // 添加悬浮窗到body
- document.body.appendChild(floatingWindow);
- makeDraggable(floatingWindow);
- }
- }
- function main() {
- const existingController = document.getElementById('video-controller');
- const existingButton = document.getElementById('toggle-button');
- if (existingController) {
- existingController.remove();
- }
- if (existingButton) {
- existingButton.remove();
- }
- videoElement = document.querySelector('video[src^="blob:https://app.kosmi.io/"]');
- if (!videoElement) {
- console.log('未找到指定视频');
- return;
- }
- controller = createController();
- makeDraggable(controller);
- createToggleButton();
- const progressContainer = document.getElementById('progress-container');
- const progressIndicator = document.getElementById('progress-indicator');
- const timeDisplay = document.getElementById('time-display');
- const volumeSlider = document.getElementById('volume-slider');
- const volumeIcon = document.getElementById('volume-icon');
- const reloadButton = document.getElementById('reload-button');
- const floatVideoButton = document.getElementById('float-video-button');
- const sizeButtons = document.querySelectorAll('.size-button');
- function updateProgress() {
- const progress = (videoElement.currentTime / videoElement.duration) * 100;
- progressIndicator.style.width = `${progress}%`;
- const current = formatTime(videoElement.currentTime);
- const total = formatTime(videoElement.duration);
- timeDisplay.textContent = `${current} / ${total}`;
- }
- progressContainer.addEventListener('click', function(e) {
- if (isDragging) return;
- const rect = progressContainer.getBoundingClientRect();
- const pos = (e.clientX - rect.left) / rect.width;
- videoElement.currentTime = pos * videoElement.duration;
- });
- volumeSlider.addEventListener('input', function() {
- videoElement.volume = this.value;
- updateVolumeIcon(this.value);
- });
- function updateVolumeIcon(volume) {
- if (volume > 0.5) {
- volumeIcon.textContent = '🔊';
- } else if (volume > 0) {
- volumeIcon.textContent = '🔉';
- } else {
- volumeIcon.textContent = '🔇';
- }
- }
- volumeSlider.value = videoElement.volume;
- updateVolumeIcon(videoElement.volume);
- reloadButton.addEventListener('click', function() {
- videoElement.removeEventListener('timeupdate', updateProgress);
- videoElement.removeEventListener('loadedmetadata', updateProgress);
- main();
- videoElement.addEventListener('timeupdate', updateProgress);
- videoElement.addEventListener('loadedmetadata', updateProgress);
- });
- floatVideoButton.addEventListener('click', createFloatingWindow);
- sizeButtons.forEach(button => {
- button.addEventListener('click', function() {
- if (!floatingWindow) return;
- const action = this.dataset.action;
- const step = 20;
- switch (action) {
- case 'increase-width':
- floatingWindow.style.width = (floatingWindow.offsetWidth + step) + 'px';
- break;
- case 'decrease-width':
- floatingWindow.style.width = Math.max(160, floatingWindow.offsetWidth - step) + 'px';
- break;
- case 'increase-height':
- floatingWindow.style.height = (floatingWindow.offsetHeight + step) + 'px';
- break;
- case 'decrease-height':
- floatingWindow.style.height = Math.max(120, floatingWindow.offsetHeight - step) + 'px';
- break;
- }
- });
- });
- videoElement.addEventListener('timeupdate', updateProgress);
- videoElement.addEventListener('loadedmetadata', updateProgress);
- }
- function waitForVideo() {
- const video = document.querySelector('video[src^="blob:https://app.kosmi.io/"]');
- if (video) {
- main();
- } else {
- setTimeout(waitForVideo, 1000);
- }
- }
- waitForVideo();
- })();