浅浅的写个简单的随机音乐播放脚本(可移动),注释很详细,直接上源码
效果:
// ==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(); // 防止拖动或正在执行费时操作文本还没改变时点击按钮
}
});
})();