Greasy Fork

Greasy Fork is available in English.

后视镜

点击悬浮球开启摄像头视频悬浮窗,再次点击悬浮球关闭视频,鼠标滚轮缩放大小,左键按住拖动位置,双击视频隐藏,再次双击隐藏位置显示视频。

当前为 2024-03-21 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         后视镜
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  点击悬浮球开启摄像头视频悬浮窗,再次点击悬浮球关闭视频,鼠标滚轮缩放大小,左键按住拖动位置,双击视频隐藏,再次双击隐藏位置显示视频。
// @author       husky180
// @match        http://*/*
// @match        https://*/*
// @exclude      http://*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    let hasVideo = false;
    let video = null;
    let cover = null;
    let videoStream = null;
    let isDragging = false;
    let offsetX = 0;
    let offsetY = 0;

    // 悬浮按钮
    var button = document.createElement('div');
    button.style.position = 'fixed';
    button.style.bottom = '20px';
    button.style.right = '20px';
    button.style.width = '50px';
    button.style.height = '50px';
    button.style.backgroundColor = 'rgba(0, 130, 220, 0.2)';
    button.style.borderRadius = '50%';
    button.style.cursor = 'pointer';
    button.style.textAlign = 'center';
    button.style.lineHeight = '50px';
    button.style.color = 'white';
    button.style.zIndex = '999999';
    button.textContent = 'Click';

    document.body.appendChild(button);

    // 悬浮按钮点击事件
    button.addEventListener('click', function() {
        if(hasVideo) {
            document.body.removeChild(video);
            document.body.removeChild(cover);
            hasVideo = false;
            video = null;
            cover = null;
            videoStream.getTracks().forEach(track => {
                track.stop();
            })
            return
        }
        hasVideo = true;
        video = document.createElement('video');
        video.id = 'huskyBackVideo';
        video.style.width = '300px';
        video.style.height = '300px';
        video.style.position = 'fixed';
        video.style.bottom = '200px';
        video.style.right = '200px';
        video.style.zIndex = '999998';
        video.autoplay = true;
        video.playsinline = true;
        // 获取摄像头视频流
        navigator.mediaDevices.getUserMedia({ video: true })
            .then(stream => {
                // 将视频流分配给 video 元素
                video.srcObject = stream;
                videoStream = stream;
            }).catch(error => {
            console.error('Error accessing the camera:', error);
        });
        document.body.appendChild(video);
        cover = document.createElement("div");
        cover.id = 'huskyBackVideoCover';
        cover.style.backgroundColor = 'rgba(255,255,255,0.5)';
        cover.style.width = '300px';
        cover.style.height = '300px';
        cover.style.zIndex = '999999';
        cover.style.position = 'fixed';
        cover.style.bottom = '200px';
        cover.style.right = '200px';
        document.body.appendChild(cover);
        cover.addEventListener("click", function(){
            if (isDragging) {
                return
            }
            if (video.style.width == "0px") {
                video.style.width = "300px";
            } else {
                video.style.width = "0px"
            }
        })
        cover.addEventListener('mousedown', function(event){
            isDragging = true;
            offsetX = event.clientX - video.offsetLeft;
            offsetY = event.clientY - video.offsetTop;
        })
        cover.addEventListener('mousemove', function(event) {
            if (isDragging) {
                // Update video element position based on mouse movement
                video.style.left = (event.clientX - offsetX) + 'px';
                video.style.top = (event.clientY - offsetY) + 'px';
                cover.style.left = (event.clientX - offsetX) + 'px';
                cover.style.top = (event.clientY - offsetY) + 'px';
            }
        });
        cover.addEventListener('mouseup', function() {
            setTimeout(() => {
                isDragging = false;
            }, 100)
        });
        // 监听鼠标滚轮事件
        cover.addEventListener('wheel', function(event) {
            // 阻止默认的滚轮事件,避免页面滚动
            event.preventDefault();

            // 判断滚轮方向
            const zoomSpeed = 0.1; // 缩放速度
            if (event.deltaY < 0) {
                // 向上滚动,放大
                video.style.width = (parseFloat(video.style.width) * (1 + zoomSpeed)) + 'px';
                video.style.height = (parseFloat(video.style.height) * (1 + zoomSpeed)) + 'px';
                cover.style.width = (parseFloat(cover.style.width) * (1 + zoomSpeed)) + 'px';
                cover.style.height = (parseFloat(cover.style.height) * (1 + zoomSpeed)) + 'px';
            } else {
                // 向下滚动,缩小
                video.style.width = (parseFloat(video.style.width) * (1 - zoomSpeed)) + 'px';
                video.style.height = (parseFloat(video.style.height) * (1 - zoomSpeed)) + 'px';
                cover.style.width = (parseFloat(cover.style.width) * (1 - zoomSpeed)) + 'px';
                cover.style.height = (parseFloat(cover.style.height) * (1 - zoomSpeed)) + 'px';
            }
        });
    });
})();