原生JS实现炫酷日食音量播放器
首先 看一下展示效果
第一步 :完成基本结构
以下是所有HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音量调节器</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="wrapper">
<audio src="./tq.mp3" preload="auto"></audio>
<div class="title">拖动调节音量</div>
<div class="per">Volume</div>
<div class="circle sun"></div>
<div class="circle moon"></div>
</div>
<script src="./index.js"></script>
</body>
</html>
先不看样式,大致要完成这样一个结构,我们把金黄色的圆称之为sun 淡黄色的圆环为moon
第二步:增加样式
样式中有两个很关键的点
- 产生自适应的两个圆
- 背景颜色的设定
在这里背景颜色采用了 hsl的设定方式,hsl有三个值 ,分别是 色相/色调 、当前的饱和度 、 当前的亮度 这样做的好处在于方便后期js操纵改变颜色
html,body{
width: 100%;
height: 100%;
/* 色相/色调 当前饱和度 当前色值亮度 */
background: hsl(194, 66%, 49%);
}
第二个注意点在于生成两个圆,其实生成两个圆的前提是生成两个正方体,这里因为是自适应的
所以要采用百分比的写法,但是这里仅仅设置了 width : 20% ,但是没有设置heght:20%
是因为 一开始width 和 height 就不是等宽的,所以他们的相对值也不可能是正方体,所以这里采用了padding-top:20% 的方式把高度撑开,实现了一个正方体
/* 自适应的正方形 */
.wrapper .circle{
position: absolute;
width: 20%;
padding-top: 20%;
/* vw vh */
border-radius: 50%;
top: 30%;
left: 30%;
}
以下是完整的css代码:
*{
margin: 0;
padding: 0;
}
html,body{
width: 100%;
height: 100%;
/* 色相/色调 当前饱和度 当前色值亮度 */
background: hsl(194, 66%, 49%);
}
.wrapper{
position: relative;
width: 70%;
height: 100%;
margin: 0 auto;
}
.wrapper .title{
position: absolute;
color: #ffffff;
top: 100px ;
font-size: 20px;
font-weight: bolder;
}
.wrapper .per{
position: absolute;
color: #ffffff;
top: 100px ;
font-size: 20px;
width: 100%;
text-align: center;
}
/* 自适应的正方形 */
.wrapper .circle{
position: absolute;
width: 20%;
padding-top: 20%;
/* vw vh */
border-radius: 50%;
top: 30%;
left: 30%;
}
.wrapper .circle.sun{
background: #ffff77;
box-shadow:0px 0px 50px #ffff77;
}
.wrapper .circle.moon{
left: 55%;
/* top: calc(30% + 2px);
width: calc(20% - 4px);
padding-top: calc(20% - 4px); */
/*
这里注释掉的部分是想让moon比sun小一圈,这样移动到中间会有一个圆环的效果,不写的话就是两个等大的圆
*/
box-shadow:inset 0 0 50px #ffff77 ;
cursor: pointer;
}
第三步:原生js增加行为
这里的编程思路是一个类似于面向对象的思路,一共有四个函数
第一个函数:init
这是一个入口函数,最后通过对象调用的方式执行整个代码
init : function(){
this.moon = document.getElementsByClassName('moon')[0] ;
this.sun = document.getElementsByClassName('sun')[0 ];
this.bindEvent();
},
主要功能是获取标签对象,执行bindEvent函数
第二个函数 : bindEvent
bindEvent : function(){
var moon = this.moon;
var body = document.getElementsByTagName('body')[0];
var dis;
var lock =false;
//这里设置了一个锁,初始状态为false
var that = this;
//这里是为了改变this 的指向 这里的this指向obj 所以that也指向obj
moon.onmousedown = function (e) {
lock = true;
//鼠标按下的时候,锁的状态变为 true
dis = e.clientX - moon.offsetLeft;
};
body.onmousemove = function (e) {
if(!lock){
return
}
//鼠标移动事件,如果鼠标在将要移动的时候,锁的状态是false,那么就直接返回出去,
// 不继续往下执行
moon.style.left = e.clientX -dis +'px';
that.getPer();
/*
这里我想要让obj调用getPer函数,如果直接this.getPer()的话,指向的应该是body,所以用that
*/
};
body.onmouseup = function () {
lock = false
//鼠标抬起之后,把锁变为false 这是moon就不会再跟着鼠标移动
};
},
这个函数的主要功能就是实现拖拽
dis = e.clientX - moon.offsetLeft;
moon.style.left = e.clientX -dis +‘px’;
这一行代码是在获取一个拖拽的值
第三个函数 :getPer
这个per 就是一个覆盖的百分比,通过水平的距离来计算,
getPer:function(){
var that = this;
var per;
var moon = that.moon;
var sun = that.sun;
var d = moon.clientWidth, // 直径
mL = moon.offsetLeft,
mR = moon.offsetLeft + d,
sL = sun.offsetLeft,
sR = sun.offsetLeft + d;
if(sL > mR || mL > sR){
per = 0
//两个圆相离的情况
}else{
//两个圆重合的情况
// 从右到左
if(sL < mL){
per = (sR - mL)/d;
// 从左到右
}else if(mR > sL){
per = (mR -sL)/d;
}
}
that.change(per);
},
第四个函数 change
change : function(per){
var audio = document.getElementsByTagName('audio')[0];
var body = document.getElementsByTagName('body')[0];
var volume = document.getElementsByClassName('per')[0];
var title = document.getElementsByClassName('title')[0];
per > 0 ? audio.play():audio.pause();
//三目运算符
audio.volume = per;
var that = this;
//改变this指向
var moon = that.moon;
moon.style.background = `hsl(194, 66%, ${
(1-per)*60}%) `;
body.style.
background = `hsl(${
194 + Math.floor(166 * per)}, 66%, ${
( 1 - per ) * 60 }%) `
// 通过改变色调和亮度改变色彩颜色
var num = new Number(per)
var str = `volume : ${
num.toFixed(2)}`;
volume.innerText = str; //将音量写入到标签中
这里主要使用了 css3属性audio 的内置方法 play()和pause( ) 用于 播放和暂停