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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端】vue3+typescript+vite+Element-Plus搭建配置初始化项目结构

给自己一个目标,然后坚持一段时间,总会有收获和感悟! 对于我们开发人员,了解和熟悉新知识,对于vue3,博主是通过TA的基本结构开始,vue2和vue3都有javascript前端编程语言,到了vue3新增…

数据库的三范式(Normalization)

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

33. 搜索旋转排序数组

题目 题解 def search(nums: List[int], target: int) -> int:if not nums:return -1l, r 0, len(nums) - 1while l < r:mid (l r) // 2if nums[mid] target:return mid# 注意判断左边升序的条件if nums[0] < nums[mid]:# 注意判断的rangeif nums[0] < targe…

C语言ASCII码排序(1086: ASCII码排序(多实例测试))

题目描述 输入三个字符后&#xff0c;按各字符的ASCII码从小到大的顺序输出这三个字符。 输入&#xff1a;输入数据有多组&#xff0c;每组占一行&#xff0c;由三个字符组成&#xff0c;之间无空格。chu 输出&#xff1a;对于每组输入数据&#xff0c;输出一行&#xff0c;字符…

【Seata源码学习 】篇三 seata客户端全局事务开启、提交与回滚

1.GlobalTransactionalInterceptor 对事务方法对增强 我们已经知道 GlobalTransactionScanner 会给bean的类或方法上面标注有GlobalTransactional 注解 和 GlobalLock的 添加一个 advisor &#xff08;DefaultPointcutAdvisor ,advisor 绑定了PointCut 的 advise) 而此处的 …

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

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

C++基础从0到1入门编程(三)

系统学习C 方便自己日后复习&#xff0c;错误的地方希望积极指正 往期文章&#xff1a; C基础从0到1入门编程&#xff08;一&#xff09; C基础从0到1入门编程&#xff08;二&#xff09; 参考视频&#xff1a; 1.黑马程序员匠心之作|C教程从0到1入门编程,学习编程不再难 2.系统…

前端为什么要工程化

前端为什么要工程化 文章目录 前端为什么要工程化传统开发的弊端一个常见的案例更多问题 工程化带来的优势开发层面的优势团队协作的优势统一的项目结构统一的代码风格可复用的模块和组件代码健壮性有保障团队开发效率高 求职竞争上的优势 现在前端的工作与以前的前端开发已经完…

高可用--限流熔断降级

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

腾讯云服务器云硬盘存储三副本消除单点故障

腾讯云服务器造可靠性处于业界领先水平的云服务器&#xff0c;云服务器CVM可靠性单实例99.975%&#xff0c;数据可靠性99.9999999%&#xff0c;云硬盘采用三副本专业存储策略&#xff0c;消除单点故障&#xff0c;保证数据可靠性&#xff0c;腾讯云百科txybk.com分享腾讯云服务…

LoRA低秩微调技术详解

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

Redis(地理空间Geospatial和HyperLogLog)

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