• 先先的音乐播放器


    0 写在前面

      进入校历第9周以来,多门课程结束了,由此为自己带来一些轻松的同时,也面临着大量的大作业以及考试等等需要应对。

      因此上一周没有练习太多的前端demo,现在将上一阶段的任务做一个了断之后,就又可以愉快的学习前端知识了!

      今天学习了h5的一个新特性<audio>标签,主要用以加载音频文件。

      为此,我练习了一个小项目,在运用一下<audio>的相关知识~

      感兴趣的朋友可以点击屏幕右上角的小猫咪访问我的github,或点击这里下载源代码进行试用~

    1 需求分析

      先看效果

      初始时,有一个太阳(左侧)和一个月亮(右侧),提示拖拽右侧的月亮来制造“日食”效果(eclipse)即可调节音频音量

      

      当开始出现“日食”时,音频开始播放

      

      随着日食的增大,音频的音量也随之增大,与此同时,为了营造“日食”氛围,需要对月亮和天空的颜色进行渐变

      

      

      

      达到最大音量(100%)后,继续延同方向拖动月亮,即可减小音量,直到月亮离开太阳时,暂停音频的播放

      

      

    2 设计分析

      经过分析,程序编写过程可以用如下的流程图进行表示。

      

    3 实现细节

    3-1 初始化结构与样式

    3-1-1 HTML5 <audio>标签  

      在HTML部分,这里我着重练习了<audio>标签的使用。

      关于<audio>标签,应该了解以下内容:

    • 浏览器支持

      Internet Explorer 9+, Firefox, Opera, Chrome 以及 Safari 支持 <audio> 标签。

      

    • <audio>属性

      

    • <audio>对象方法

      

    • <audio>对象属性

      

      

      以上图片内容来源于W3School

      在本次的练习中,我使用到的是src属性获取音频地址,preload="auto"忽略该属性。

      HTML结构部分代码比较简单,如下所示

      

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     7     <title>MusicPlayer</title>
     8     <link rel="stylesheet" href="demo.css">
     9 </head>
    10 <body>
    11     <div class="wrapper">
    12         <audio src="source/song.mp3" id="audio" preload="auto"></audio>
    13         <div class="title">Justify volume by dragging the moon to eclipse the sun!</div>
    14         <div class="per">Volume</div>
    15         <div class="circle sun"></div>
    16         <div class="circle moon"></div>
    17         <div class="author">Chris.Chen Copyright 2019 All rights reserved.</div>
    18     </div>
    19     <script src="demo.js"></script>
    20 </body>
    21 </html>

    3-1-2  初始样式设计

      在初始样式设计中练习了3个知识点:

    • hsl函数设置颜色:hsl的三个参数分别代表色相(即颜色)、饱和度和亮度。这里我用到的是 background: hsl(194,66%,49%);来设置天空的背景颜色。

    • box-shadow:这是CSS3的一个新特性

        他的用法是这样的 box-shadow: h-shadow v-shadow [blur] [spread] [color] [inset]

        其中,h-shadow v-shadow两个参数表示水平和垂直方向上阴影的偏移值,为必填参数

        而, [blur]模糊距离 [spread]阴影尺寸 [color]阴影颜色 和[inset]设置为内阴影,为可选参数

        在本练习中,我采用的样式是

        box-shadow: 0 0 50px #ff7; 作为太阳的阴影,水平垂直不偏移(即均匀分布的阴影),模糊距离50px,颜色为#ff7

        box-shadow: inset 0px 0px 50px rgba(255,255,119,0.3); 作为月亮的阴影,设置了inset即向内的阴影。

    • 重点:自适应的圆形    

               宽度相对于父级的20%,但高度若设成相对于父级的20%可能会出问题,因为父级未必是正方形

          解决方案是将高度设为0,并设置padding-top

      初始化样式部分的代码如下:

     1 *{
     2     margin: 0;
     3     padding: 0;
     4 }
     5 html,body{
     6     height: 100%;
     7     width: 100%;
     8     /* 色相 饱和度 亮度 */
     9     background: hsl(194,66%,49%);
    10 }
    11 .wrapper{
    12     width: 70%;
    13     height: 100%;
    14     margin: 0 auto;
    15     /* border: 1px solid #000; */
    16     position: relative;
    17 }
    18 .wrapper .title{
    19     position: absolute;
    20     top: 100px;
    21     width: 100%;
    22     /* text-align: center; */
    23     color: #fff;
    24     font-size: 24px;
    25     font-weight: bold;
    26 }
    27 .wrapper .per{
    28     position: absolute;
    29     top: 20%;
    30     width: 100%;
    31     height: 40px;
    32     text-align: center;
    33     color: #fff;
    34     font-size: 20px;
    35     font-weight: bold;
    36 }
    37 .wrapper .circle{
    38     /* 重点:实现自适应的圆形 */
    39     /* 宽度相对于父级的20%,但高度若设成相对于父级的20%可能会出问题,因为父级未必是正方形 */
    40     /* 解决方案是将高度设为0,并设置padding-top */
    41     width: 20%;
    42     padding-top: 20%;
    43     position: absolute;
    44     /* border: 1px solid #000; */
    45     border-radius: 50%;
    46     top: 30%;
    47     left: 30%;
    48 }
    49 .wrapper .circle.sun{
    50     background: #ffff77;
    51     box-shadow: 0 0 50px #ff7;
    52 }
    53 .wrapper .circle.moon{
    54     /* 留出两个圆形之间的空隙 */
    55     left: 52%;
    56     /* inset向里阴影,阴影左右偏移量,阴影上下偏移量,阴影宽度,阴影颜色 */
    57     box-shadow: inset 0px 0px 50px rgba(255,255,119,0.3);
    58     cursor: pointer;
    59 }
    60 .wrapper .author{
    61     width: 100%;
    62     text-align: center;
    63     color: #fff;
    64     font-size: 16px;
    65     position: absolute;
    66     bottom: 15%;
    67 }

    3-2 鼠标事件绑定

      到了JS部分,今天在练习中,还着重练习的一点是面向对象的思想,因此将今天实现的功能全部挂载到了一个obj对象上,在对象内部试图通过this来进行访问。

      但是有一个问题就是,在为dom元素绑定鼠标事件的时候会改变this指向,导致this指向了当前dom元素,从而无法取得obj的属性或方法。

      在这里用到的一个技巧,就是在obj内部添加一个变量var self = this保存一下指向当前obj的this

      鼠标共涉及3种事件:鼠标落下、移动和抬起,落下绑定在moon对象上,而移动和抬起则绑定在body对象上,这是为了放置鼠标移动过快导致鼠标脱离了moon的区域。

      原对象e可以通过e.clientX,e.clientY获取鼠标点击的横纵坐标,通过计算前后坐标之间的差值,并更新dom对象的style,即可实现拖拽效果。

      在抬起取消移动的设计上,可以用body.onmousemove = null 也可以用在本次练习中的写法那样,加一个flag锁控制,若抬起鼠标则释放锁,在onmousemove的函数中直接返回

      在移动中,随时调用比例计算函数。

    3-3 覆盖比例计算

      覆盖比例需要分情况讨论。

      首先通过moon.clientWidth获取这个dom对象的宽(即月亮的直径),这个值用于后面的比例计算。

      需要分月亮在太阳的左或是右,两种情况进行讨论和计算。

      比例的计算方法为:重叠长度 / 直径

      注意边界:当太阳雨月亮相离时,直接设置比例为0。

      将计算得的比例作为参数传入并调用调整方法。

    3-4 音量与背景调节

      调节部分比较简单,获取到了比例计算的结果之后,即可根据这一比例进行设置dom元素的属性改变情况了。

      audio.play()方法可以播放指定audio对象的音频

      audio.pause()方法可以暂停指定audio对象的音频

      audio.volume属性可以设置指定audio对象音频的音量,取值为[0,1]

      其他调整还包括对文字提示innerHTML的调整和对style.background颜色的调整

    3-5 行为控制JS代码

     1 var obj = {
     2     init:function(){
     3         // 这里与jquery不同,字符串直接写类名即可,无需在前面加.
     4         this.moon = document.getElementsByClassName('moon')[0];
     5         this.sun  = document.getElementsByClassName('sun')[0];
     6         this.bindEvent();
     7     },
     8     bindEvent:function(){
     9         var moon = this.moon;
    10         var body = document.getElementsByTagName('body')[0];
    11         var dis;
    12         var self = this;
    13         var flag = false;
    14         moon.onmousedown = function(e){
    15             dis = e.clientX - moon.offsetLeft;
    16             flag = true;
    17         };
    18         body.onmousemove = function(e){
    19             if(!flag) return;
    20             moon.style.left = (e.clientX - dis) + 'px';
    21             self.getPer();
    22         };
    23         body.onmouseup = function(e){
    24             flag = false;
    25         };
    26     },
    27     getPer:function(){
    28         var self = this; 
    29         var sun = self.sun;
    30         var moon = self.moon;
    31         var per;
    32         var d = moon.clientWidth,
    33         mL = moon.offsetLeft,
    34         mR = moon.offsetLeft + d,
    35         sL = sun.offsetLeft,
    36         sR = sun.offsetLeft + d;
    37         if(mL > sR || mR < sL){
    38             per = 0;
    39         }
    40         else{
    41             if(sL < mL){
    42                 per = (sR - mL) / d;
    43             }
    44             else if(mR > sL){
    45                 per = (mR - sL) / d;
    46             }
    47         }
    48         self.change(per);
    49     },
    50     change:function(vol){
    51         var audio = document.getElementsByTagName('audio')[0];
    52         var body = document.getElementsByTagName('body')[0];
    53         var per = document.getElementsByClassName('per')[0];
    54         var moon = this.moon;
    55         vol > 0 ? audio.play():audio.pause();
    56         audio.volume = vol;
    57         var str = "Volume:" + (vol*100).toPrecision(4) + "%";
    58         per.innerHTML = str;
    59         moon.style.background = "hsl(194,66%," + (1 - vol) * 60 + "%)";
    60         body.style.background = "hsl(" + (194 + Math.floor(166*vol)) + ", 66%," + (1 - vol) * 50 + "%)";
    61     }
    62 }
    63 
    64 obj.init();
  • 相关阅读:
    Python 基础 字符串拼接 + if while for循环
    JTable 的使用方法
    java与数据库连接的几个步骤
    socket通信 _ 一个简单的群聊系统
    基本的文件读写
    多线程之碰撞小球
    java类的继承
    java类和对象
    java中的关键字
    java 线程实现方式
  • 原文地址:https://www.cnblogs.com/chrischen98/p/10761130.html
Copyright © 2020-2023  润新知