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

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

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

// ==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(); // 防止拖动或正在执行费时操作文本还没改变时点击按钮
        }
    });



})();

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

斯坦福机器学习 Lecture1

https://www.bilibili.com/video/BV1JE411w7Ub?p1&vd_source7a1a0bc74158c6993c7355c5490fc600 笔记如下 机器学习的定义:不需要明确编程就能让计算机去学习做某件事情 另一个定义 TODO:here

【网络】OSI模型 与 TCP/IP模型 对比

一、OSI模型 OSI模型包含7个层次,从下到上分别是: 1. 物理层(Physical Layer) - 功能:处理与电子设备物理接口相关的细节(如电压、引脚布局、同步,等等)。 - 协议:以…

clusterProfiler包学习

&#x1f4d6; Introduction | Biomedical Knowledge Mining using GOSemSim and clusterProfiler (yulab-smu.top) 部分使用 #GO classificationlibrary(clusterProfiler) data(geneList, package"DOSE") gene <- names(geneList)[abs(geneList) > 2]# Entre…

cesium雷达扫描(模糊圆效果)

cesium雷达扫描(模糊圆效果) 1、实现思路 使用ellipse方法加载圆型,修改ellipse中‘material’方法重写自己的glsl来实现当前效果 1、示例源码 index.html <!DOCTYPE html> <html lang="en"><head><!<

常见树种(贵州省):002杉类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、杉木 …

9、传统计算机视觉 —— 边缘检测

本节介绍一种利用传统计算机视觉方法来实现图片边缘检测的方法。 什么是边缘检测? 边缘检测是通过一些算法来识别图像中物体之间,或者物体与背景之间的边界,也就是边缘。 边缘通常是图像中灰度变化显著的地方,标志着不同区域的分界线。 在一张图像中,边缘可以是物体的…

TURN 协议

TURN 地址分配 抓包过程 TURN 连接建立 这里指的是 Client 收到对端从 TURN 分配的 IP 和 端口 &#xff0c;和对端的 TURN 和 IP 绑定的过程 CreatePermission Request 等消息&#xff0c;都会携带有对端的 TURN 和 IP 抓包过程

新手必看!!超详细!STM32-基本定时器

一、基本定时器的作用 定时触发输出直接驱动DAC。 二、基本定时器的框图 以STM32F103系列为例&#xff0c;具体开发板请查看开发手册。 类别定时器总线位数计数方向预分频系数是否可以产生DMA捕获/比较通道互补输出基本定时器TIM6 / TIM7APB116位向上1~65536可以0无通用定时…

五、hdfs常见权限问题

1、常见问题 2、案例 &#xff08;1&#xff09;问题 &#xff08;2&#xff09;hdfs的超级管理员 &#xff08;3&#xff09;原因 没有使用Hadoop用户对hdfs文件系统进行操作。 在Hadoop文件系统中&#xff0c;Hadoop用户相当于Linux系统中的root用户&#xff0c;是最高级别用…

Linux每日智囊-cat, more, less

每日分享三个Linux命令&#xff0c;悄悄培养读者的Linux技能。 cat 作用 在终端显示文件内容 cat命令允许创建单个或多个文件&#xff0c;查看文件的内容&#xff0c;连接文件并在终端或文件中重定向输出。 语法 cat [选项] 文件 参数&#xff1a; -n:显示行数&#xf…

MySQL进阶_8.数据库其他调优策略

文章目录 第一节、数据库调优的步骤1.1、选择合适的DBMS1.2、优化表设计1.3、优化逻辑查询1.4、优化物理查询1.5、使用 Redis 或 Memcached 作为缓存1.6、库级优化 第二节、优化MySQL服务器第三节、优化数据库结构 第一节、数据库调优的步骤 1.1、选择合适的DBMS 如果对事务性…

read系统调用源码分析

文章目录 基本知识前言一个文件基本的读写流程图块设备驱动<1> 块设备&#xff08;blockdevice&#xff09;<2> 块设备结构<3> block_device和gendisk 区别 同步/异步IO请求队列 read系统调用源码分析设计思想一、入口函数&#xff08;1&#xff09;fget_lig…

MySQL 的执行原理(二)

5.3. MySQL 的查询成本 5.3. MySQL 的查询成本 MySQL 执行一个查询可以有不同的执行方案&#xff0c;它会选择其中成本最低&#xff0c;或者 说代价最低的那种方案去真正的执行查询。不过我们之前对成本的描述是非常模 糊的&#xff0c;其实在 MySQL 中一条查询语句的执行成本…

FPGA语法相关知识合集

一.相关概念 1.四种结构说明语句 2.initial 与 always 的异同点 3.task 与 function 的3个不同点 4.task的语法结构(定义及调用) 5.function的语法结构(定义及调用) 6.function 的一个必须有和一个必须没有&#xff0c;使用规则 7.自动&#xff08;递归&#xff09;函数…

腾讯云CVM服务器标准型/高IO/计算/大数据使用场景及选择说明

腾讯云CVM服务器多种机型使用场景说明&#xff0c;如标准型、内存型、高 IO 型、计算型、大数据型、异构型和批量型&#xff0c;腾讯云百科txybk.com分享不同CVM实例规格配置适合使用场景说明&#xff1a; 腾讯云CVM云服务器 标准型&#xff1a;适合中小型 Web 应用、中小型数据…

振南技术干货集:CPU,你省省心吧!(2)

注解目录 1、石油测井仪器 1.1 背景知识 &#xff08;了解一下石油行业。石油到底是怎么找到的&#xff1f;&#xff09; 1.2 测井数据采传的实现 1.2.1 最直接的初级方案 1.2.2 加入 DMA 的优化方案 &#xff08;看看一般工程师与高手在技术实现上到底有什么区别。充分…

2023 鹏程杯

前言 笔者没有参加此次比赛&#xff0c;由于团队后面会复现此次比赛&#xff0c;所以笔者在此进行复现记录。 silent 考点: 栈溢出 ret2csu 栈迁移 保护: 开了 Full RELRO 和 NX, 禁掉了 execve/execveat 系统调用 漏洞分析 一个裸的栈溢出, 但是没有输出函数可以泄漏 …

C语言--有 n 个人围成一圈,顺序排号。 从第 1 个人开始报数,从 1 到 3 报数,凡是报到 3 的人退出圈子,问最后留下的是原来的第几号?

今天小编给大家分享以下约瑟夫环问题的处理。 一.题目描述 有 n 个人围成一圈,顺序排号。 从第 1 个人开始报数,从 1 到 3 报数,凡是报到 3 的人退出圈子,问最后留下的是原来的第几号? 这是一个典型的约瑟夫环的问题。 二.思路分析 难点一&#xff1a;我们如何表示人退出圈…

基于Springboot的地方美食分享网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的地方美食分享网站(有报告)。Javaee项目&#xff0c;springboot项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 项目介绍&#xff1a; 采用…

BUUCTF snake 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 下载附件&#xff0c;解压得到一张snake的图片。 密文&#xff1a; 这里有一张蛇的图片&#xff0c;本人害怕不敢放&#xff0c;想看自己下载附件解压。&#xff08;吐槽一下&#xff0c;我做这道题&#xff0c;全…