油猴脚本(JavaScript)-练手-简单的随机音乐播放器

news2024/11/18 17:29:58

浅浅的写个简单的随机音乐播放脚本(可移动),注释很详细,直接上源码

效果:
在这里插入图片描述

// ==UserScript==
// @name         播放音乐脚本
// @namespace    代码对我眨眼睛
// @version      1.2
// @description  在API上请求音乐链接并随机自动连续播放音乐,带有可拖动的界面控制按钮
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// ==/UserScript==

//封装一个立即执行函数
(function() {
    //使用严格模式
    'use strict';

    // 添加样式
    GM_addStyle(
        //添加按钮样式
        `
        #musicToggle {
            position: fixed;
            top: 10px;
            left: 10px;
            padding: 5px;
            background-color: #65d7ed;
            color: #3a8bff;
            cursor: move;
            z-index: 1000;
        }
    `);

    let audioElement; // 定义音频元素以便在函数之间共享,用以判断音频是否存在或者播放完毕
    let ing=0;//判断脚本是否正在音频之中,以防多次点击
    let isMusicPlaying = false;//用于追踪音乐是否正在播放
    let isMusicPaused = false; // 用于追踪音乐是否暂停
    /*移动前的x和y的位置,移动后的x和y的位置,是否为拖动行为判断*/
    let dragStartX, dragStartY, offsetX = 0, offsetY = 0, isDragging = false;
    /*在html的body后一面动态的添加一个div元素,模拟一个按钮的形状*/
    const toggleButton = document.createElement('div');
    /*给按钮命名id */
    toggleButton.id = 'musicToggle';
    /*给按钮加上文本 */
    toggleButton.textContent = '播放音乐';

    // 添加按钮到页面
    document.body.appendChild(toggleButton);

    // 请求并播放音乐函数
    function playMusic(url) {
        //因为前面判断过了,一般不会有这种存在音频还申请的情况,以防万一
        if (audioElement) {
            audioElement.pause(); // 如果存在当前音频,则暂停它
        }
        //申请一个新音频(这个api会自动随机)
        audioElement = new Audio(url);
        //播放音频
        audioElement.play();
        //开启监听函数,当音频播放完成时
        audioElement.addEventListener('ended', function() {
            //将播放状态设为否
            isMusicPlaying = false;
            //如果没有暂停
            if (!isMusicPaused) {
                //调用请求函数
                requestMusic();
            }
        });
        //在函数内已经播放了,这个返回值没有上,无伤大雅
        //(叫什么来着,保持函数结构的完整性 bushi)
        return audioElement;
    }

    // 发起请求的函数
    function requestMusic() {
        GM_xmlhttpRequest({
            method: 'GET',
            url: 'http://api.sc1.fun/API/changyam.php',
            onload: function(response) {
                //申请返回内容
                const url = response.responseText;
                //播放内容对应的地址
                playMusic(url);
                isMusicPlaying = true; // 设置标志表示音乐正在播放
            },
            //报错
            onerror: function(error) {
                console.error('请求音乐失败:', error);
            }
        });
    }

    // 切换音乐播放状态
    function toggleMusic() {
        if (audioElement) {
            //console.log(`暂停音乐`);
            //加入需要耗费时间的进程了,先标记禁用一下按钮防止多次请求
            ing=1;
            //如果正在播放
            if (isMusicPlaying) {
                audioElement.pause(); // 暂停音频
                //将按键文本调成·播放音乐·
                document.getElementById('musicToggle').textContent = '播放音乐';
                
                isMusicPlaying = false;
                isMusicPaused = true;
            }  //如果停止播放
            else {
                audioElement.play(); // 恢复播放音频
                //将按键文本调成·停止音乐·
                document.getElementById('musicToggle').textContent = '停止播放';

                isMusicPaused = false;
                isMusicPlaying = true;
            }
            //耗费时间的进程加载完了,标记加载结束开启按键响应
            ing=0;
        } else {
            //同上
            ing=1;
            // 如果没有音频元素,则开始播放
            //console.log(`没有音频元素,则开始播放`);
            //申请播放新音频
            requestMusic();
            //将将按键文本调成·停止音乐·,即目前正在播放
            document.getElementById('musicToggle').textContent = '停止播放';
            //同上
            ing=0;
        }
    }

    // 鼠标按下时记录初始位置
    toggleButton.addEventListener('mousedown', function(e) {
        //记录开始按下时的x和y坐标
        dragStartX = e.clientX;
        dragStartY = e.clientY;
        //先将拖动标志设为false,因为暂时无法判断是否拖动
        isDragging = false;
        //将鼠标的图标换成抓手的图案
        toggleButton.style.cursor = 'grabbing';
        //如果按下以后鼠标有所移动则进入是否拖动的判断函数
        document.addEventListener('mousemove', dragMove);
        //当鼠标抬起则进入最后的操作函数
        document.addEventListener('mouseup', dragEnd);
    });

    // 鼠标移动时计算偏移量并更新按钮位置
    function dragMove(e) {
        //如果超出阈值则判定为拖动,否则直接返回(即点击时手抖轻微拖动或者已经停下了的情况)
        if (!isDragging) {
            const distance = Math.sqrt((e.clientX - dragStartX) ** 2 + (e.clientY - dragStartY) ** 2);
            if (distance > 5) {  // 设置您所需的拖动阈值
                //拖动判断标志设为真
                isDragging = true;
            } else {
                return;
            }
        }
       //计算拖动的x和y的距离
        offsetX += e.clientX - dragStartX;
        offsetY += e.clientY - dragStartY;
         //随时改变拖动的位置
        toggleButton.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
        //存储按钮新的位置
        dragStartX = e.clientX;
        dragStartY = e.clientY;
    }

    // 鼠标释放时
    function dragEnd(e) {
        //将鼠标样式设为拖动
        toggleButton.style.cursor = 'move';
        
        //监听完毕去掉按键抬起和移动的事件监听,
        //因为这两个监听可以被按下的操作启用,
        //这样可以优化性能和防止冲突
        document.removeEventListener('mouseup', dragEnd);
        document.removeEventListener('mousemove', dragMove);

    }

    // 为按钮添加点击事件监听器
    toggleButton.addEventListener('click', function(e) {
        //如果不是拖动操作时并且未执行费时操作时则正常操作
        if ((!isDragging)&&(ing==0)) {
            toggleMusic();
        }
        //否则
        else {
            e.preventDefault(); // 防止拖动或正在执行费时操作文本还没改变时点击按钮
        }
    });



})();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1226257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决向日葵远程控制linux命令行版本无法输入密码的问题

就是如下所示的框,官方说是按方向键↓选择用户名和密码的输入框输入,但是按方向键死活没用,研究了之后按tab键就行了。

WMS仓库管理系统库位分配规划

分配说明 每个商品必须至少有一个分拣位(整箱或拆零均可)如果只设了拆零分拣位,则入库不分配存储位,只上拆零分拣位,对于DPS分拣商品是一品固定一个货位,对于RF分拣商品是动态分配货位,一个商品…

Java集合大总结——List的简单使用

List简单介绍 鉴于Java中数组用来存储数据的局限性,我们通常使用java.util.List替代数组List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。 List…

Linux:清空或删除大文件内容的5种方法

在Linux终端下处理文件时,有时我们想直接清空文件的内容但又不必使用任何Linux命令行编辑器 去打开这些文件。那怎样才能达到这个目的呢?在这篇文章中,我们将介绍几种借助一些实用的命令来清空文件内容的方法。 注意:在我们进一步…

美国政府首席信息安全官详细介绍零信任战略竞赛

如果企业想吸取教训,为庞大的组织快速制定零信任战略,他们应该看看美国联邦政府在 2024 年之前让所有机构合规的努力。 这就是被任命为联邦办公室 CISO(首席信息安全官) 的克里斯德鲁沙 (Chris DeRusha) 的看法。 周三&#xf…

OpenAI变天:也许会有另一个OpenAI要崛起?

本周五,OpenAI发布重磅声明,创始人兼CEO山姆奥特曼辞任OpenAI,并退出董事会。总裁Greg Brockman(格雷格布罗克曼)将辞去董事会主席一职,但将继续在公司担任职务,向CEO汇报。 作为吃瓜群众&#…

[CUDA]去除Eigen库中的warning

一、问题提出 假如使用nvcc对cuda代码进行编译时,如果代码中使用了Eigen库(头文件),编译时可能会显示很多warning information,如下图红框中所示: 这些warning信息虽然不会影响代码的实际运行,…

【WiFI问题自助】解决WiFi能连上但是没有网的问题

WiFi能连上但是没有网的问题 背景:wifi能连上,但是没有网 解决 遇事不决,先重启啊!怎么重启?拔掉电源再插上!拔掉网线再插上! 直接ok了。 思考记录 今天WiFi又上不了网了,昨天报…

C语言三位数求解(ZZULIOJ1076:三位数求解)

题目描述 已知xyzyzzn,其中n是一个正整数,x、y、z都是数字(0-9),编写一个程序求出x、y、z分别代表什么数字。如果无解,则输出“No Answer”注意:xyz和yzz表示一个三位数,而不是表示x…

高可用--限流熔断降级

熔断 熔断是应对微服务雪崩效应的一种链路保护机制。 场景 服务端出现问题 服务指标:响应时间、错误率、连续错误数等,超过阈值出发熔断。硬件指标:CPU、网络IO、内存 目的 服务端恢复需要时间、服务端需要休息避免全调用链路崩溃&…

memcacheredis构建缓存服务器

一、缓存服务器: 1、简介: ① 许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示。 但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、 网站显示延迟等重大影响。 ● RDBMS&…

Windows 下提取EXE文件中的图标

可以使用两种工具: 1 使用 IconViewer 下载地址: https://www.botproductions.com/iconview/download.html 2 使用 QuickAny2Ico 下载地址: Quick Any2Ico - Create icons from any source 2.1 操作步骤 样例(采用 python-3.7.9.exe 作为例子提取为…

MyBatis 操作数据库(构造动态 SQL)

前言 动态 SQL 是 Mybatis 的强⼤特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接。 <if> 标签 我们在填写用户信息的时候经常会看到如下的界面&#xff0c;用户信息中包含必填信息和非必填信息&#xff0c;非必填信息是填和不填都可以的&#xff0c;那这样的话…

UDS 14229-1定义的请求的响应行为

UDS服务响应规则 重要提示服务器一般响应行为包含子功能的请求响应行为物理寻址请求功能寻址请求 没有子功能参数的服务响应行为物理寻址客户端请求功能寻址客户端请求 伪代码示例 重要提示 服务应当支持物理寻址方式请求&#xff0c;部分服务也支持功能寻址方式请求。在功能寻…

Linux tc 使用

tc模拟延时丢包等网络故障依赖的内核驱动 /lib/modules/5.15.0-52-generic/kernel/net/sched/sch_netem.ko有些系统并不是默认就安装上该驱动的&#xff0c;如果没有安装该驱动&#xff0c;构造网络故障时会报错。 root:curtis# tc qdisc change dev enp4s0 root netem delay…

LoRA低秩微调技术详解

在当今快节奏的技术环境中&#xff0c;大型AI模型正在推动不同领域的突破。 然而&#xff0c;根据特定任务或数据集定制这些模型可能是一项计算和资源密集型工作。 LoRA是一种突破性且高效的微调技术&#xff0c;它利用这些高级模型的强大功能来执行自定义任务和数据集&#xf…

Word 2016 删除标注

步骤&#xff1a; 菜单栏--审阅--删除--删除文档中的所有标注

07.webpack的性能优化 -- 产出代码

目标&#xff1a; 体积更小合理分包&#xff0c;不重复加载速度更快&#xff0c;使用内存更小 实现功能 小图片的base64编码提取公共代码bundle加hashIngorePlugin懒加载使用CDN使用productionScope Hosting 1. 使用production module.exports smart(webpackCommonConf, …

Python武器库开发-flask篇之session与cookie(二十六)

flask篇之session与cookie(二十六) 在 Flask 中&#xff0c;可以使用 session 来在不同请求之间存储和传递数据。Session 在客户端和服务器端之间交换&#xff0c;但是数据存储在服务器端。 Session 与 Cookie 的区别 session 和 cookie 都可以用来在不同请求之间存储和传递…

Vue3-readonly(深只读) 与 shallowReadonly(浅只读)

Vue3-readonly(深只读) 与 shallowReadonly&#xff08;浅只读&#xff09; readonly(深只读)&#xff1a;具有响应式对象中所有的属性&#xff0c;其所有值都是只读且不可修改的。shallowReadonly(浅只读)&#xff1a;具有响应式对象的第一层属性值是只读且不可修改的&#x…