zoukankan      html  css  js  c++  java
  • 先先的音乐播放器

    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();
  • 相关阅读:
    I.MX6 Surfaceflinger 机制
    理解 Android Fragment
    RPi 2B DDNS 动态域名
    RPi 2B IPC webcam server
    理解 Android MVP 开发模式
    I.MX6 system.img unpack repack
    can't set android permissions
    VMware Ubuntu 共享文件夹
    解决oracle数据库连接不上的问题
    perfect-scrollbar示例
  • 原文地址:https://www.cnblogs.com/chrischen98/p/10761130.html
Copyright © 2011-2022 走看看