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

news2024/11/18 15:36:17

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

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

// ==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/1226295.html

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

相关文章

【Python3】【力扣题】303. 区域和检索 - 数组不可变

【力扣题】题目描述: 【Python3】代码: 1、解题思路:从列表中获取指定下标的所有元素,求和。 知识点:列表[start:end]:切片。从列表中获取起始下标start(含)到结束下标end&#xf…

Redis(地理空间Geospatial和HyperLogLog)

Geospatial: Redis中的Geospatial提供了一种存储和处理地理空间数据的能力,这对于许多应用非常有用。以下是Redis中的Geospatial的一些作用: 1. 地理位置查询:可以存储地理位置的坐标信息,并且可以通过查询指定半径范…

数据库的三范式(Normalization)

数据库的三范式(Normalization)是关系数据库设计中的基本理论原则,旨在减少数据冗余和提高数据库的数据组织结构。三范式通过将数据分解为更小的表,并通过关系建立连接,使得数据库设计更加灵活、规范和容易维护。在这篇…

【csapp lab】lab2_bomblab

文章目录 前言实验内容phase_1phase_2phase_3phase_4phase_5phase_6secret_phase 前言 刚做了csapp lab2,记录一下。 我这里用的的系统环境是Ubuntu22.04,是64位系统,与用32位系统可能有所差异。 实验共包括七个阶段,每个阶段考…

湖北成人自考毕业学位申请照片要求及自拍制作方法

湖北成人自考学位申请需要上传照片是为了身份验证和学籍管理的目的。通过上传照片,学校可以确认申请者的身份,并将照片与其他申请信息进行关联。这有助于提高学校对学生的管理效率,确保学籍信息的准确性。同时,照片也用于学位证书…

基于FPGA的五子棋(论文+源码)

1.系统设计 在本次设计中,整个系统硬件框图如下图所示,以ALTERA的FPGA作为硬件载体,VGA接口,PS/2鼠标来完成设计,整个系统可以完成人人对战,人机对战的功能。系统通过软件编程来实现上述功能。将在硬件设计…

计算机硬件的基本组成

一、冯诺依曼结构 存储程序: “存储程序”的概念是指将指令以二进制代码的形式事先输入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一条指令,以后就按该程序的规定顺序执行其他指令,直至程序执行结束。 冯诺依曼计…

C语言每日一题(33)随机链表的复制

力扣138 随机链表的复制 题目描述 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都…

理论与实践相结合之Cisco Packet Tracer网络模拟器安装教程

简介 Packet Tracer是由思科设计的跨平台可视化仿真工具,它允许用户创建网络拓扑以模仿计算机网络和使用命令行界面来模拟配置思科路由器和交换机。Packet Tracer的用户界面为拖放式,允许用户根据自己的需要添加和删除模拟的网络设备。 Packet Tracer很…

卡片排列-第15届蓝桥第二次STEMA测评Scratch真题精选

[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第159讲。 第15届蓝桥杯第2次STEMA测评已于2023年10月29日落下帷幕,编程题一共有6题,分别如下&…

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

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

如何将vscode和Linux远程链接:

如何将vscode和Linux远程链接&#xff1a; Remote - SSH - 远程登录Linux 安装Remote - SSH 我们下载完后&#xff0c;就会出现这些图标 这里点一下号 查看一下我们的主机名&#xff0c;并复制 输入ssh 用户名主机名 这里是要将ssh这个文件要放在主机下的哪个路径下&#xff…

最强人工智能ChatGPT引领AIGC发展

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- ——AI不会淘汰所有人&#xff0c;但会淘汰不懂AI的人 一、最强人工智能GPT-4 Turbo 在前不久的OpenAI开发者大会&#xff0c;正值Chatgpt3.5发布一…

微信第三方平台开发重点概念流程梳理

标题 微信开发的亿点点概念第三方平台代开发流程亿些概念开发流程 代公众号使用JS SDK一些概念具体流程引用 微信开发的亿点点概念 AppID&#xff1a;AppID是不同类型的产品的账号ID,是账号的唯一标识符。例如公众号的AppID、小程序的AppID、开放平台的AppID、第三方平台的App…

C++之内建函数对象

C之内建函数对象 算术仿函数 #include<iostream> using namespace std; #include<functional>//内建函数对象头文件 //内建函数对象 算术仿函数void test() {// negate 一元仿函数 取反仿函数negate<int>n;cout << n(100) << endl;//plus 二元仿…

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

浅浅的写个简单的随机音乐播放脚本(可移动)&#xff0c;注释很详细&#xff0c;直接上源码 效果&#xff1a; // UserScript // name 播放音乐脚本 // namespace 代码对我眨眼睛 // version 1.2 // description 在API上请求音乐链接并随机自动连续播放音乐&…

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

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

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

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

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

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

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

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