V LIVE Video Rotation

Adds buttons to rotate and flip the video.

目前为 2019-03-06 提交的版本。查看 最新版本

// ==UserScript==
// @name        V LIVE Video Rotation
// @description Adds buttons to rotate and flip the video. 
// @version     1.0
// @author      aqmx
// @namespace   aqmx
// @license     MIT
// @match       *://www.vlive.tv/video/*
// @grant       GM_addStyle
// ==/UserScript==


GM_addStyle(`
.vlive_info {
	overflow: hidden;
}
.vlive_info .tit {
	display: block;
	margin-bottom: 9px;
}
.vlive_info .status_area {
	display: inline-flex;
	align-items: center;
}
.vlive_info .ico_blue {
	margin-right: unset;
}
.vlive_info .txt, .vlive_info .like, .vlive_info .date {
	margin-top: 0;
}
.vlive_info .icon_play, .vlive_info .icon_like {
	margin-top: 1px;
}

#video-rotation-controls {
	position: relative;
	display: inline-block;
	margin-left: 15px;
	z-index: 1;
}
#video-rotation-controls button {
	font-size: 20px;
	background: #f5f5f5;
	border: 1px solid #d9d9d9;
	color: #414141;
	margin-top: -4px;
	line-height: 22px;
	height: 24px;
	width: 24px;
	outline: 0;
}
`);


let rotations = {
	r90: 'rotate(90deg)',
	r180: 'rotate(180deg)',
	r270: 'rotate(270deg)',
};
let scaling = {
	flipH: 'scaleX(-1)',
	flipV: 'scaleY(-1)',
	portrait: 'scale(1.759)',
	landscape: 'scale(0.559)',
};
let stylesheet = null;

(() => {
	stylesheet = document.createElement('style');
	document.head.appendChild(stylesheet);

	let getAllSubsets = arr => arr.reduce((subsets, value) => subsets.concat(subsets.map(set => [...set, value])), [[]]).slice(1);
	let scalings = getAllSubsets(Object.keys(scaling));

	for (let rule in rotations) {
		stylesheet.sheet.insertRule('video.'+rule+' { transform: '+rotations[rule]+'; }', stylesheet.sheet.cssRules.length);
		for (let scalingSet of scalings) {
			stylesheet.sheet.insertRule('video.' + rule + '.' + scalingSet.reduce((s, v) => s+'.'+v) + ' { transform: ' + rotations[rule] + scalingSet.reduce((s, v) => s+' '+scaling[v], '') + '; }', stylesheet.sheet.cssRules.length);
		}
	}

	let flips = getAllSubsets(['flipH', 'flipV']);
	for (let flipSet of flips) {
		stylesheet.sheet.insertRule('video.' + flipSet.reduce((s, v) => s+'.'+v) + ' { transform:' + flipSet.reduce((s, v) => s+' '+scaling[v], '') + '; }', stylesheet.sheet.cssRules.length);
	}
})();

function addButtion() {
	let btnArea = document.querySelector('#content .vlive_section .vlive_info .btn_area');
	if (!btnArea) {
		setTimeout(addButtion, 500);
		return;
	}

	let div = document.createElement('div');
	div.id = 'video-rotation-controls';
	div.innerHTML = `
	<button data-direction="r270">🠘</button>
	<button data-direction="0">🠙</button>
	<button data-direction="r90">🠚</button>
	<button data-direction="r180">🠛</button>
	<button data-direction="flipV">🡙</button>
	<button data-direction="flipH">🡘</button>`;
	btnArea.parentNode.insertBefore(div, btnArea);

	document.querySelector('#video-rotation-controls').addEventListener('click', function(e) {
		if (e.target.tagName.toLowerCase() != 'button') return;
		let video = document.querySelector('.u_rmcplayer_video video') || document.querySelector('.vwplayer_vlivelive .videoBox video');
		if (!video) return;
		let flip = ['flipH', 'flipV'].includes(e.target.dataset.direction);
		if (flip) {
			video.classList.toggle(e.target.dataset.direction);
		}
		else {
			video.classList.remove('r90', 'r180', 'r270', 'portrait', 'landscape');
			if (e.target.dataset.direction != '0') {
				video.classList.add(e.target.dataset.direction);
				if (['r90', 'r270'].includes(e.target.dataset.direction)) {
					video.classList.add(video.videoHeight > video.videoWidth ? 'portrait' : 'landscape');
				}
			}
		}
	});
}

addButtion();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址