脚本(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/164041.html

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

相关文章

【MySQL--->事务】

文章目录 [TOC](文章目录) 一、基本概念二、事务的操作1.设置全局事务隔离级别2.设置事务提交方式3.事务操作 三、事务隔离性1.隔离性概念2 .隔离级别设置 四、MVCC多版本控制2. read view 一、基本概念 事务是由若干条具有逻辑相关性的SQL语句组成的,用来完成某种任务的**逻辑…

使用 C 语言快速排序将字符串按照 ASCII 码升序排列

示例代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h>static Comp(const void *a, const void *b) {char *pa (char *)a;char *pb (char *)b;return strcmp(a, b); }int main(void) {char strs[3][10] { "bd", &q…

SpringBoot 整合 JdbcTemplate

数据持久化有几个常见的方案&#xff0c;有 Spring 自带的 JdbcTemplate 、有 MyBatis&#xff0c;还有 JPA&#xff0c;在这些方案中&#xff0c;最简单的就是 Spring 自带的 JdbcTemplate 了&#xff0c;这个东西虽然没有 MyBatis 那么方便&#xff0c;但是比起最开始的 Jdbc…

关于爬虫中的hook(defineProperty,hook cookies, hook载荷数据,hookXHR)

关于爬虫中的hook&#xff1a; defineProperty var people {age: 19, }; var count20; console.log(people.age) // 参数&#xff1a;对象 属性名字 函数 Object.defineProperty(people, age, {get: function () {console.log(获取值&#xff01;);return count;},// set: …

C++ map和set的使用

关联式容器 vector、list、deque统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;存储的是元素本身 侧重于单纯的存储数据 关联式容器也是用来存储数据的&#xff0c;里面存储的是<key, value>结构的键值对&#xff0c;在数据检索时比序列式…

漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(2)

书接上文漫谈广告机制设计 | 万剑归宗&#xff1a;聊聊广告机制设计与收入提升的秘密&#xff08;1&#xff09;&#xff0c;我们谈到流量作为一种有限资源&#xff0c;其分配方式&#xff08;或者交易方式&#xff09;也经历了几个阶段&#xff1a;第一个是谈判定价阶段&#…

新材料工厂生产管理mes系统

万界星空科技新材料云MES系统从需求分析、产品选型、系统集成、可扩展性和灵活性以及安全性和稳定性等多个角度进行考虑。 如果您的企业也属于新材料生产制造行业&#xff0c;同时也计划通过MES系统来进行整个生产过程的数字化管控。 欢迎搜索万界星空科技线上咨询或者直接拨…

论文阅读:JINA EMBEDDINGS: A Novel Set of High-Performance Sentence Embedding Models

Abstract JINA EMBEDINGS构成了一组高性能的句子嵌入模型&#xff0c;擅长将文本输入转换为数字表示&#xff0c;捕捉文本的语义。这些模型在密集检索和语义文本相似性等应用中表现出色。文章详细介绍了JINA EMBEDINGS的开发&#xff0c;从创建高质量的成对&#xff08;pairwi…

搭建网关服务器实现DHCP自动分配、HTTP服务和免密登录

目录 一. 实验要求 二. 实验准备 三. 实验过程 1. 网关服务器新建网卡并改为仅主机模式 2. 修改新建网卡IP配置文件并重启服务 3. 搭建网关服务器的dhcp服务 4. 修改server2网卡配置文件重启服务并效验 5. 设置主机1的网络连接为仅主机模式 6. 给server2和网关服务器之…

YOLOv4 学习记录

文章目录 整体概况数据增强Mosaic数据增强 基于CSPNet网络思想的架构改进Mish激活函数CSPNetCSPNet 3 大优势Partial Transition 层 CSPDarkNet (yolo v4 中的CSPDarkNet53) NeckSPPNetPAN-FPN 结构 正负样本匹配损失函数IOU 损失函数IOU的2个问题&#xff1a; GIOU Loss示意图…

力扣hot100 两数之和 哈希表

&#x1f468;‍&#x1f3eb; 力扣 两数之和 &#x1f60b; 思路 在一个数组中如何快速找到某一个数的互补数&#xff1a;哈希表 O(1)实现⭐ AC code class Solution {public int[] twoSum(int[] nums, int target){HashMap<Integer, Integer> map new HashMap<&g…

STM32CubeMX学习笔记(2)--DSP库的使用

1.DSP库简介 STM32的DSP库是为了支持数字信号处理应用而设计的&#xff0c;它包含了一系列优化的数学函数和算法&#xff0c;能够在STM32微控制器上高效地执行数字信号处理任务。 DSP库通常包括以下主要特性&#xff1a; 1.数学函数库&#xff1a; 包括各种基本的数学运算函数…

STM32电源名词解析

先来简单了解一下各种电源端口的命名 VCC&#xff1a;Ccircuit 表示电路的意思, 即接入电路的电压 VDD&#xff1a;Ddevice 表示器件的意思, 即器件内部的工作电压。 VSS&#xff1a;Sseries 表示公共连接的意思&#xff0c;通常指电路公共接地端电压。 GND&#xff1a;在电…

设计模式——责任链模式

文章目录 责任链模式的定义场景示例责任链模式实现方案责任链模式扩展责任链模式的优缺点责任链模式在框架源码中的应用 责任链模式的定义 责任链模式又称职责链模式&#xff0c;是一种行为型设计模式。官方描述&#xff1a;使多个对象都有机会处理请求&#xff0c;从而避免请…

Python 如何实现职责链设计模式?什么是职责链设计模式?Python 职责链设计模式示例代码

什么是职责链&#xff08;Chain of Responsibility&#xff09;设计模式&#xff1f; 职责链&#xff08;Chain of Responsibility&#xff09;设计模式是一种行为型设计模式&#xff0c;旨在构建一个对象链&#xff0c;每个对象都有机会处理请求&#xff0c;并且可以将请求传…

C++初阶 | [三] 类和对象(中)

摘要&#xff1a;类的6个默认成员函数&#xff0c;日期类 如果一个类中什么成员都没有&#xff0c;简称为空类。然而&#xff0c;空类并不是什么成员都没有&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成6个默认成员函数。默认成员函数&#xff1a;用户没有显式…

python中列表的基础解释

列表&#xff1a; 一种可以存放多种类型数据的数据结构 列表的创建&#xff1a; 1.用【】创建列表 #创建一个空列表 list1[] #创建一个非空列表 list2 [zhang,li,ying,1,2,3] #输出内容及类型 print(list1,type(list1)) print(list2,type(list2))结果&#xff1a; 2.使用list…

《视觉SLAM十四讲》-- 回环检测

文章目录 10 回环检测10.1 概述10.1.1 回环检测的意义10.1.2 回环检测的方法10.1.3 准确率和召回率 10.2 词袋模型10.3 字典10.3.1 字典的结构10.3.2 实践&#xff1a;创建字典 10.4 相似度计算10.4.1 理论部分10.4.2 实践&#xff1a;相似度的计算 10.5 实验分析与评述 10 回环…

股票价格预测 | Python实现基于CNN卷积神经网络的股票预测模型(keras,Conv1D)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 股票价格预测 | Python实现基于CNN卷积神经网络的股票预测模型(keras) 源码设计 import quandl import datetimedf = quandl

FreeRTOS(教程非常详细)

概述&#xff1a; 之前写了关于FreeRTOS的部分内容&#xff0c;为了方便阅读&#xff0c;现在给汇总到一起了。全部学习完后&#xff0c;恭喜你对FreeRTOS有了更深的认知。 第一章 FreeRTOS移植到STM32 第二章 FreeRTOS创建任务 第三章 FreeRTOS任务管理 第四章 FreeRTOS消…