YouTube Mousemove Volume Control

Drag the mouse's middle button to set volume according to where the cursor is along the width of the video.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         YouTube Mousemove Volume Control
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  Drag the mouse's middle button to set volume according to where the cursor is along the width of the video.
// @author       Rasutei
// @match        https://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        none
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @license      GNU GPLv3
// ==/UserScript==
/* eslint-disable curly */

// ----- Utility stuff -----
var $ = window.jQuery;
const logcss = `
	font-family: Hack, monospace;
	text-shadow: 0 0 10px black, 0 0 10px black;
	background: linear-gradient(to right, #4d94ff 0%, #4d94ff 8px, rgb(77 148 255 / 30%) 8px, transparent 50px);
	color: #4d94ff;
	padding: 2px 0 2px 30px;
	`
const warncss = `
	font-family: Hack, monospace;
	text-shadow: 0 0 10px black, 0 0 10px black;
	background: linear-gradient(to right, #ffa621 0%, #ffa621 0% 8px, rgb(255 166 33 / 30%) 8px, transparent 50px);
	color: #ffa621;
	padding: 2px 0 2px 30px;
	`
const log = (e) => console.log('%c'+e, logcss)
const warn = (e) => console.log('%c'+e, warncss)
const warn_element = (e) => console.log('%c%o', warncss, e)

// ----- Variables and elements -----
const spn = $('<span id="ras-volumebar-text">')
	.css('color','black')
	.css('font-size','17px')
	.css('font-family','Hack')
const fill = $('<div id="ras-volumebar-fill">')
	.append(spn)
	.css('position','relative')
	.css('left','0')
	.css('top','0')
	.css('height','100%')
	.css('transition','width 50ms ease')
	.css('background-color','white')
	.css('display','flex')
	.css('align-items','center')
	.css('justify-content','center')
	.css('overflow','hidden')
	.css('padding','0 4px')
const bar = $('<div id="ras-volumebar">')
	.append(fill)
	.css('position','absolute')
	.css('top','50%')
	.css('left','50%')
	.css('transform','translate(-50%, -50%)')
	.css('width','300px')
	.css('height','20px')
	.css('border','3px solid black')
	.css('outline','1px solid white')
	.css('background-color','rgb(0 0 0 / 50%)')
	.fadeToggle(0)
const wrapper = $('<div id="ras-vidwrapper">')
	.append(bar)
	.css('position','relative')
	.css('margin','auto')
let vid
let isMDown = false
let isSetVolume = false
let hasMouseMoved = false
let rect

// ----- Actual code -----
$(document).ready(function(){
	log('RDrag Volume: Applying script...')

	// ----- Importing a nice font I've been enjoying as of late -----
	let hackfont = document.createElement('link')
	hackfont.setAttribute('rel','stylesheet')
	hackfont.setAttribute('type','text/css')
	hackfont.setAttribute('href','//cdn.jsdelivr.net/npm/[email protected]/build/web/hack-subset.css')

	// ----- Loop to check if page has a video -----
	let prev_url = window.location.href
	setInterval(() => {
		if (document.querySelector('#ras-vidwrapper'))
			return
		if (window.location.href != prev_url)
			prev_url = window.location.href
		if (window.location.href.includes('/watch?v=')) {

			// ----- Attach nice font -----
			document.head.appendChild(hackfont)

			// ----- Find video element -----
			vid = $('video.video-stream')

			// ----- Attach utility to video element -----
			vid[0].parentElement.append(wrapper[0])

			// ----- Apply video's size to wrapper element -----
			new ResizeObserver(() => {
				wrapper.css('width',vid.css('width'))
				wrapper.css('height',vid.css('height'))
			}).observe(vid[0])

			// ----- Getting wrapper's rect -----
			rect = wrapper[0].getBoundingClientRect()

			log('RDrag Volume: Script applied.')
		}
	}, 100)

	// ----- Mouse event handling -----
	rect = wrapper[0].getBoundingClientRect()
	wrapper.mousedown((evemt) => {
		let interval
		if (event.which == 2){
			event.preventDefault()
			event.stopPropagation()
			isSetVolume = true
			rect = wrapper[0].getBoundingClientRect()
			bar.fadeIn(100)
			SetVolume(event)
			interval = setInterval(() => {
				if (!document.hasFocus()){
					StopSetting()
					clearInterval(interval)
				}
			}, 32)
		}
	})
	wrapper.mouseup((event) => {
		if (!event.which == 3) return
		StopSetting()
	})
	wrapper.mouseleave((event) => {
		StopSetting()
	})
	wrapper.mousemove((event) => {
		if (!isSetVolume) return
		SetVolume(event)
	})
	window.blur(() => {
		warn('Blurred')
		StopSetting()
	})
})

// ----- Auxiliary functions to prevent repeats -----
function StopSetting(){
	//warn('StopSetting')
	isSetVolume = false
	bar.delay(300).fadeOut(100)
}
function SetVolume(event){
	//warn('SetVolume')
	let vol = (event.clientX - rect.left) / rect.width
	let per = (vol*100).toFixed(1)+'%'
	vid[0].volume = vol
	spn.text(per)
	fill.css('width', per)
}