JavaScript + Audio API自制简易音乐播放器(详细完整版、小白都能看懂)

JavaScript + Audio API自制简易音乐播放器(详细完整版)

**

音乐播放器的功能清单如下:

**
1.点击暂停按钮,歌曲暂停
2.点击播放按钮,歌曲播放
3.单曲循环与取消单曲循环
4.当播放到列表最后一首歌曲时,点击下一首自动切换到列表中的第一首
5.当播放到列表第一首歌曲时,点击上一首自动切换到列表中的最后一首
6.一键静音与非静音
7.增大减小音量(既可通过鼠标点击操作,也可通过键盘上下键操作)
8.下一首、上一首
9.快进、快退
10.进度条随这音乐播放实时变化
11.歌曲已播放时长实时变化
12.点击进度条区域可以进行快进快退,已播放时长和进度条的进度也同步更新
13.鼠标点击拖动进度条的红点(小方块)可以进行快进快退,已播放时长和进度条的进度也同步更新

首先来看一下效果图:
音乐播放器
在这里插入图片描述
这是我的目录结构:
在这里插入图片描述

JavaScript部分的难点:
1.多媒体事件的运用
2.获取Dom对象
3.设置flag记录true false的小技巧,来达到在同一个元素上点击,出现不同的效果
4.鼠标事件的灵活运用
5.通过Dom对象动态修改样式
6.设置定时器
7.键盘事件

CSS部分难点:
1.渐变色
2.pointer-events: none;可以让某个元素实现类似于海市蜃楼的效果,具体理解为,你可以看的到某个元素,但是你无法摸的着。
3.相对定位
4.绝对定位
5.flex弹性盒子布局
6.精灵图background属性的灵活运用
7.属性zoom: 0.2; 强制缩放
zoom牵一发动全身,zoom:0.5后 ,width和height都会变成原来的一半 ;
而transform: scale(0.5) div height200px,width:200px, scale(0.5)即为缩小为原来的一半时,他的height和width还是200px, 只不过里面的元素缩小了而已。

page.js部分的代码如下:

var arrys = ["./songs/晴天 周杰伦.mp3","./songs/时间停了 鹿晗.mp3","./songs/光辉岁月 Beyon.mp3","./songs/栀子花开 何炅.mp3","./songs/纸短情长 烟把儿乐队.mp3"
];var audio = document.createElement("audio");
audio.src = arrys[0];
// 多媒体(Media)事件:
// canplaythrough 事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。
// durationchange 事件在视频/音频(audio/video)的时长发生变化时触发。
// pause 事件在视频/音频(audio/video)暂停时触发。
// play 事件在视频/音频(audio/video)开始播放时触发。
// volumechange 事件在音量发生改变时触发。
// ended 事件在视频/音频(audio/video)播放结束时触发。
// error 事件在视频/音频(audio/video)数据加载期间发生错误时触发。
// canplay 事件在用户可以开始播放视频/音频(audio/video)时触发。 
// timeupdate 事件在当前的播放位置发送改变时触发。audio.addEventListener("canplaythrough", function() {console.log('music ready');
}, false);
audio.addEventListener("timeupdate", showTime, true);function showTime() {duration = formatTime(audio.duration);currenttime = formatTime(audio.currentTime);document.getElementById('totaltime').innerHTML = duration.M + ':' + duration.S;document.getElementById('currenttime').innerHTML = currenttime.M + ':' + currenttime.S;//获取当前播放的百分比  当前进度/总进度var percent = audio.currentTime / audio.duration//拼接进度条的widthvar swidth = (percent * 255) + "px";//设置进度条的播放进度document.getElementById("bar").style.width = swidth;document.getElementById("dot").style.left = swidth;
}
// 播放
function aPlay() {audio.play();
}
// 暂停
function aPause() {audio.pause();
}
// 快进
function go() {audio.currentTime += 10;audio.play();runToPause();
}
// 快退
function back() {audio.currentTime -= 10;audio.play();runToPause();
}// 将播放图标切换为暂停图标
function runToPause(){runDom[0].style.display = 'none';pauseDom[0].style.display = 'inline-block';
}
// 将暂停图标切换为播放图标
function PauseToRun(){runDom[0].style.display = 'inline-block';pauseDom[0].style.display = 'none';
}quietDom = document.getElementsByClassName('quiet');
noquietDom = document.getElementsByClassName('noquiet');
// 将静音图标切换为非静音图标
function quietToNo(){quietDom[0].style.display = 'none';noquietDom[0].style.display = 'inline-block';
}// 将非静音图标切换为静音图标
function noToquiet(){quietDom[0].style.display = 'inline-block';noquietDom[0].style.display = 'none';
}// 增大音量
function add() {audio.volume != 1 ? audio.volume += 0.1 : 1;console.log(audio.volume);if (audio.volume >= 0.001) {quietToNo();console.log('noquiet')}
}// 减小音量
function subtract() {audio.volume != 0 ? audio.volume -= 0.1 : 0;console.log(audio.volume);if (audio.volume <= 0.001) {noToquiet();console.log('quiet')}
}// 静音
var qFlag = 0; // 是否静音
function isquiet() {qFlag = !qFlag;// if(qFlag){// 	audio.volume = 0;	// 	console.log(audio.volume);// }else{// 	audio.volume = 0.5;// }	audio.volume = !audio.volume;}
// 静音图标切换为非静音图标
function quiet() {quietToNo();isquiet();
}// 非静音图标切换为静音图标
function noquiet() {noToquiet();isquiet();
}// 时间格式转换
function formatTime(seconds) {var h = 0,i = 0,s = Math.floor(seconds);h = Math.floor(s / 3600);i = Math.floor((s % 3600) / 60);s = s % 3600 % 60;return {H: h = h < 10 ? "0" + h : h,M: i = i < 10 ? "0" + i : i,S: s = s < 10 ? "0" + s : s};
};//设置播放源
var currMp3 = arrys[0];
//上一曲,并实现循环播放
function prev() {tmpMp3 = "";arrys.forEach(function(item, index) {// 通过循环找到与当前播放的音乐相同的那一个item,目的是为了拿到当前的indexif (item == currMp3) {if (index == 0) {tmpMp3 = arrys[arrys.length - 1];} else {//下一个tmpMp3 = arrys[index - 1];}console.log(tmpMp3)audio.src = tmpMp3;setTimeout(function() {audio.play()currMp3 = tmpMp3;}, 500)return;}})run(); // 把播放图标切换成暂停图标并播放音乐
}// 下一曲,并实现循环播放
function next() {tmpMp3 = "";arrys.forEach(function(item, index) {if (item == currMp3) { // 当找到当前播放的歌曲时,进入if代码执行块if ((index + 1) == arrys.length) {//说明是最后一个tmpMp3 = arrys[0];} else {//下一个tmpMp3 = arrys[index + 1];}console.log(tmpMp3)audio.src = tmpMp3;setTimeout(function() { // 设置定时器,在点击下一曲按钮时生效,audio.play(); // play() 方法开始播放当前的音频或视频。currMp3 = tmpMp3; // 将当前播放音乐的路径更新到currMp3中保存}, 500)return;}})run(); // 把播放图标切换成暂停图标,并播放音乐
}var flag = 0; // 是否点击了单曲循环按钮,点了为1,没点为0
// 当前歌曲播放完后,自动切换下一首
audio.addEventListener('ended', function() {if (flag) {arrys.forEach(function(item, index) {if (item == currMp3) {tmpMp3 = arrys[index]}setTimeout(function() {audio.play()currMp3 = tmpMp3;}, 500)})} else {next();}
}, false);// 实现单曲循环
function circle() {console.log('单曲循环')flag = !flag; // 是否点击了单曲循环按钮,点了为1,没点为0console.log(flag);
}document.onkeyup = function(event) { //键盘事件var vol = 0.1; //1代表100%音量,每次增减0.1var time = 10; //单位秒,每次增减10秒// console.log("keyCode:" + event.keyCode);console.log("volume" + audio.volume);var e = event || window.event || arguments.callee.caller.arguments[0];// 键盘事件:
// 属性 描述 DOM
// keydown 某个键盘按键被按下。
// keypress 某个键盘按键被按下并松开。
// keyup 某个键盘按键被松开。//实现键盘按上下键控制音乐的音量,按左右键控制音乐的快进快退if (e && e.keyCode === 38) {// 按 向上键audio.volume !== 1 ? audio.volume += vol : 1;if (audio.volume >= 0.001) {quietToNo();console.log('noquiet')}return false;} else if (e && e.keyCode === 40) {// 按 向下键audio.volume !== 0 ? audio.volume -= vol : 1;if (audio.volume <= 0.001) {noToquiet();console.log('quiet')}return false;} else if (e && e.keyCode === 37) {// 按 向左键audio.currentTime !== 0 ? audio.currentTime -= time : 1;return false;} else if (e && e.keyCode === 39) {// 按 向右键audio.volume !== audio.duration ? audio.currentTime += time : 1;return false;} else if (e && e.keyCode === 32) {// 按空格键 判断当前是否暂停audio.paused === true ? audio.play() : audio.pause();if (audio.paused === false) {runToPause();} else {pauseToRun();}return false;}};
runDom = document.getElementsByClassName('run');
pauseDom = document.getElementsByClassName('pause');
// 点击播放按钮切换为暂停按钮
function run() {runToPause();aPlay();
}
// 暂停按钮切换为播放按钮
function pause() {PauseToRun();aPause();
}// 鼠标事件:
// onclick 当用户点击某个对象时调用的事件句柄。
// ondblclick 当用户双击某个对象时调用的事件句柄。
// onmousedown 鼠标左键被按下。
// onmouseenter 当鼠标指针移动到元素上时触发。
// onmouseleave 当鼠标指针移出元素时触发
// onmousemove 鼠标被移动。
// onmouseover 鼠标移到某元素之上。
// onmouseout 鼠标从某元素移开。
// onmouseup 鼠标左键被松开。window.onload = function() {var scrollDom = document.getElementById('scroll');var barDom = document.getElementById('bar');var dotDom = document.getElementById('dot');// 鼠标左键被按下。scrollDom.onmousedown = function(event) {// console.log("111" + event.offsetX);// 鼠标被移动scrollDom.onmousemove = function(event) {// console.log(event.offsetX);// console.log("offsetLeft" + event.offsetLeft)barDom.style.width = event.offsetX + "px";dotDom.style.left = (event.offsetX) + "px";pause();}}// 鼠标移到某元素上scrollDom.onmouseover = function() {scrollDom.onmousemove = null;}// 鼠标左键被松开scrollDom.onmouseup = function(e) {scrollDom.onmousemove = null; //鼠标左键松开后不做任何操作currentX = e.offsetX;var oWidth = scrollDom.offsetWidth; // 元素整体宽度 :边框+内容区var cWidth = scrollDom.clientWidth; // 元素内容区宽度 :内容区var percents = (currentX / cWidth).toFixed(2);// console.log(percents + '%!')audio.currentTime = audio.duration * percents;run();}scrollDom.onclick = function(e) {console.log(e.offsetX);currentX = e.offsetX;barDom.style.width = e.offsetX + "px";dotDom.style.left = (e.offsetX) + "px";var oWidth = scrollDom.offsetWidth; // 元素整体宽度 :边框+内容区var cWidth = scrollDom.clientWidth; // 元素内容区宽度 :内容区var percents = (currentX / cWidth).toFixed(2);// console.log(percents + '%')// console.log(audio.duration * percents)// console.log(formatTime(audio.duration * percents))audio.currentTime = audio.duration * percents;}}

index.html部分的代码如下:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>简易音乐播放器</title><link rel="stylesheet" href="./css/style.css"><script src="./js/page.js"></script></head><body><div id="all"><div class="speed"><div class="back" οnclick="back()" id="back" title="快退"></div><div class="go" οnclick="go()" id="go" title="快进"></div></div><div class="players"><div class="container clearfix"><div class="left clearfix"><div class="prev" οnclick="prev()" title="上一首"></div><div class="run" οnclick="run();" title="播放"></div><div class="pause" οnclick="pause();" title="暂停"></div><div class="next" οnclick="next()" title="下一首"></div></div><div class="middle"><div class="scroll" id="scroll"><div class="bar" id="bar"><div class="dot" id="dot"></div></div></div><div class="music_detail"><div id="currenttime">00:00</div><div class="line"> / </div><div id="totaltime">00:00</div></div></div><div class="right"><div class="circle" οnclick="circle()" title="单曲循环"></div><div class="quiet" οnclick="quiet()" id="quiet" title="取消静音"></div><div class="noquiet" οnclick="noquiet()" id="noquiet" title="静音"></div><div class="verticle"><div class="add" οnclick="add()" id="add" title="增加音量"></div><div class="subtract" οnclick="subtract()" id="subtract" title="减小音量"></div></div></div></div></div></div></body>
</html>

style.css部分的代码如下:

#progressBar {width: 80%;height: 32%;background: #e9e9e9;position: relative;
}#playProgressBar {position: absolute;top: 0;left: 0;background: #20bfd8;height: 100%;width: 100%;
}#ptxt {width: 100%;height: 30px;text-align: center;font-size: 16px;line-height: 30px;z-index: 10;position: absolute;
}* {margin: 0;padding: 0;
}body {margin: 0 auto;
}
.speed{display: flex;align-items: center;justify-content: center;
}
#all{margin: 200px;
}.clearfix:after {content: '';display: block;visibility: none;clear: both;
}/* 播放图标 */
.run {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -267px -20px;zoom: 0.3;}/* float: left; */
/* zoom牵一发动全身,zoom:0.5后 ,width和height都会变成原来的一半 */
/*而transform: scale(0.5) div height200px,width:200px, scale(0.5)即为缩小为原来的一半时,他的height和width还是200px, 只不过里面的元素缩小了而已。 *//* 暂停图标 */
.pause {display: none;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -517px -517px;zoom: 0.3;
}/* zoom牵一发动全身,zoom:0.5后 ,width和height都会变成原来的一半 */
/*而transform: scale(0.5) div height200px,width:200px, scale(0.5)即为缩小为原来的一半时,他的height和width还是200px, 只不过里面的元素缩小了而已。 *//* 下一首图标 */
.next {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -765px -266px;zoom: 0.2;
}/* 上一首图标 */
.prev {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -14px -271px;zoom: 0.2;
}/* 单曲循环图标 */
.circle {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -514px -23px;zoom: 0.2;
}/* 增大音量图标 */
.add {display: inline-block;width: 90px;height: 90px;background-image: url(../img/voice.jpg);background-position: -163px -125px;zoom: 0.25;
}/* 减小音量图标 */
.subtract {display: inline-block;width: 90px;height: 90px;background-image: url(../img/voice.jpg);background-position: -37px -125px;zoom: 0.25;
}/* 静音图标 */
.quiet {display: none;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -517px -762px;zoom: 0.2;
}/* 非静音图标 */
.noquiet {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -20px -762px;zoom: 0.2;
}/* 快进图标 */
.go {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -515px -268px;zoom: 0.2;
}/* 快退图标 */
.back {display: inline-block;width: 220px;height: 217px;background-image: url(../img/icons.jpg);background-position: -268px -268px;zoom: 0.2;
}.players {box-sizing: border-box;width: 770px;height: 110px;background-image: linear-gradient(#436881, #ea9e0d);padding: 13px 0;border-radius: 25px 10px 25px 10px;/* 左上角,右上角,右下角,左下角 */margin: 0 auto;}.container {width: 96%;height: 97%;background-color: white;margin: 0 auto;display: flex;justify-content: space-around;
}.left {width: 23%;height: 100%;display: flex;justify-content: space-around;align-items: center;
}.middle {width: 53%;height: 100%;align-items: center;display: flex;padding: 20px;box-sizing: border-box;
}.right {width: 16%;height: 100%;display: flex;justify-content: space-around;align-items: center;
}.verticle {width: 15%;align-items: center;height: 69%;
}.music_detail {display: flex;}#currenttime {font-size: 13px;line-height: 35px;margin-left: 20px;
}#totaltime {font-size: 13px;line-height: 35px;
}.line {font-size: 13px;line-height: 35px;
}
.scroll{width: 500px;height: 13px;background-color: gray;
}
.bar{width: 0px;height: 13px;background-color: aquamarine;position: relative;pointer-events: none;/* pointer-events: none; 可以让某个元素实现类似于海市蜃楼的效果,具体理解为,你可以看的到某个元素,但是你无法摸的着。 */cursor: move;
}
.dot{width: 5px;height: 13px;background-color: red;position: absolute;left: 0px;top: 0px;
}

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

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

相关文章

jQuery实现PC端商城购物车模块基本功能(每个商品的小计和合计都会根据添加和删除的操作来动态计算)

jQuery实现PC端商城购物车模块基本功能 先上效果图&#xff1a; 因为主要是想练习jQuery的使用&#xff0c;所以页面CSS部分比较简陋&#xff0c;有需要的话&#xff0c;大家在参考代码时&#xff0c;可以自己再完善下CSS部分的代码&#xff0c;让购物车页面更加美观。 功能…

七、CSS 三大特性(完整详细解析)

** CSS 三大特性&#xff08;完整详细解析&#xff09; ** 1.优先级&#xff1a; 定义CSS样式时&#xff0c;经常出现两个或更多规则应用在同一元素上&#xff0c;此时&#xff0c; 选择器相同&#xff0c;则执行层叠性选择器不同&#xff0c;就会出现优先级的问题。 1&am…

LeetCode 2114. 句子中的最多单词数

文章目录1. 题目2. 解题1. 题目 一个 句子 由一些 单词 以及它们之间的单个空格组成&#xff0c;句子的开头和结尾不会有多余空格。 给你一个字符串数组 sentences &#xff0c;其中 sentences[i] 表示单个 句子 。 请你返回单个句子里 单词的最多数目 。 示例 1&#xff1…

一、css清除浮动方法学习笔记总结(超详细,简单易懂)

** css清除浮动方法学习笔记总结&#xff08;超详细&#xff0c;简单易懂&#xff09; ** 问题&#xff1a; 上图中&#xff0c;由于container(父级元素&#xff09;未设置高度&#xff0c;其内部子元素设置了float浮动&#xff0c;导致与container同级&#xff08;也就是co…

LeetCode 2115. 从给定原材料中找到所有可以做出的菜(拓扑排序)

文章目录1. 题目2. 解题1. 题目 你有 n 道不同菜的信息。给你一个字符串数组 recipes 和一个二维字符串数组 ingredients 。 第 i 道菜的名字为 recipes[i] &#xff0c;如果你有它 所有 的原材料 ingredients[i] &#xff0c;那么你可以 做出 这道菜。一道菜的原材料可能是 另…

C语言makefile文件详解,makefile讲解

仅供自己学习使用一、Makefile介绍Makefile 或 makefile: 告诉make维护一个大型程序&#xff0c; 该做什么。Makefile说明了组成程序的各模块间的相互 关系及更新模块时必须进行的动作&#xff0c; make按照这些说明自动地维护这些模块。执行make命令时&#xff0c;需要一个 Ma…

二、MySQL连接查询学习笔记(多表连接查询:内连接,外连接,交叉连接详解)

MySQL连接查询&#xff08;多表连接查询&#xff1a;内连接&#xff0c;外连接&#xff0c;交叉连接详解&#xff09; 6&#xff1a;多表连接查询 笛卡尔乘积&#xff1a;如果连接条件省略或无效则会出现 解决办法&#xff1a;添加上连接条件连接查询的分类&#xff1a; 1.按…

android 本机号码一键登录,什么是本机号码一键登录?APP本机号码一键登录如何实现?...

三大运营商推出一键登录的服务后&#xff0c;由于其便捷性和安全性都好于传统短信验证码&#xff0c;越来越多的APP注册登录环节都在使用本机号码一键登录验证方式。本文主要介绍了本机号码一键登录特点以及实现方法。一、什么是本机号码一键登录&#xff1f;平时我们填手机号接…

LeetCode 2116. 判断一个括号字符串是否有效(栈)

文章目录1. 题目2. 解题1. 题目 一个括号字符串是只由 ( 和 ) 组成的 非空 字符串。 如果一个字符串满足下面 任意 一个条件&#xff0c;那么它就是有效的&#xff1a; 字符串为 ().它可以表示为 AB&#xff08;A 与 B 连接&#xff09;&#xff0c;其中A 和 B 都是有效括号字…

NavigationController

前面的一篇文章《iOS开发16&#xff1a;使用Navigation Controller切换视图》中的小例子在运行时&#xff0c;屏幕上方出现的工具栏就是Navigation Bar&#xff0c;而所谓UINavigationItem就可以理解为Navigation Bar中的内容&#xff0c;通过编辑UINavigationItem&#xff0c;…

android studio windows,AndroidStudio的使用(Windows)

演示模式View---Enter presentation mode演示代码快捷提示commondshfita最近修改的文件ctrlshfite代码书签在一行代码处使用F11也可以在navigate--bootmarkPaste_Image.png回退到上一个浏览的地方ctrlaltleft/right快速进入方法内ctrlb查看方法的参数定义commondpPaste_Image.p…

LeetCode 2119. 反转两次的数字

文章目录1. 题目2. 解题1. 题目 反转 一个整数意味着倒置它的所有位。 例如&#xff0c;反转 2021 得到 1202 。反转 12300 得到 321 &#xff0c;不保留前导零 。 给你一个整数 num &#xff0c;反转 num 得到 reversed1 &#xff0c;接着反转 reversed1 得到 reversed2 。 …

三、MySQL子查询学习笔记(标量子查询、列子查询、行子查询、表子查询 详解)

三、MySQL子查询学习笔记 7&#xff1a;子查询 含义&#xff1a; 一条查询语句中又嵌套了另一条完整的select语句&#xff0c;其中被嵌套的select语句&#xff0c;称为子查询或内查询&#xff1b;在外面的查询语句&#xff0c;称为主查询或外查询 分类&#xff1a; 一、按子查…

LeetCode 2120. 执行所有后缀指令(模拟)

文章目录1. 题目2. 解题1. 题目 现有一个 n x n 大小的网格&#xff0c;左上角单元格坐标 (0, 0) &#xff0c;右下角单元格坐标 (n - 1, n - 1) 。 给你整数 n 和一个整数数组 startPos &#xff0c;其中 startPos [startrow, startcol] 表示机器人最开始在坐标为 (startrow…

android代理生命周期,了解 Activity 生命周期

当用户浏览、退出和返回到您的应用时&#xff0c;您应用中的在生命周期回调方法中&#xff0c;您可以声明用户离开和再次进入 Activity 时 Activity 的行为方式。例如&#xff0c;如果您正构建流媒体视频播放器&#xff0c;当用户切换至另一应用时&#xff0c;您可能要暂停视频…

LeetCode 2121. 相同元素的间隔之和(前缀和)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始、由 n 个整数组成的数组 arr 。 arr 中两个元素的 间隔 定义为它们下标之间的 绝对差 。更正式地&#xff0c;arr[i] 和 arr[j] 之间的间隔是 |i - j| 。 返回一个长度为 n 的数组 intervals &#xff0c;其中 interva…

在android添加数据采集,一种基于Android系统的地理信息数据采集方法与流程

本方法属于采集地理信息数据的发明&#xff0c;是一种基于android操作系统和gis地理信息系统进行户外地理信息数据采集的方法。背景技术&#xff1a;众所周知地理信息数据采集在很多行业中都有应用&#xff0c;比如说农业中的土地普查、城市管理中的地下管线普查、工业中的地质…

LeetCode 2124. 检查是否所有 A 都在 B 之前

文章目录1. 题目2. 解题1. 题目 给你一个 仅 由字符 a 和 b 组成的字符串 s 。 如果字符串中 每个 ‘a’ 都出现在 每个 ‘b’ 之前&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;s "aaabbb" 输出&#x…

设计模式—桥接模式

前言 这里以电视遥控器为例子引出桥接模式&#xff0c;首先每个牌子的电视都有一个遥控器&#xff0c;可以设计吧遥控器作为一个抽象类&#xff0c;抽象类中提供遥控器的所有实现&#xff0c;其他具体电视品牌的遥控器都继承这个抽象类 这样的实现使得每个不同型号的电视都有自…

LeetCode 2125. 银行中的激光束数量

文章目录1. 题目2. 解题1. 题目 银行内部的防盗安全装置已经激活。 给你一个下标从 0 开始的二进制字符串数组 bank &#xff0c;表示银行的平面图&#xff0c;这是一个大小为 m x n 的二维矩阵。 bank[i] 表示第 i 行的设备分布&#xff0c;由若干 ‘0’ 和若干 ‘1’ 组成。…