likes
comments
collection
share

写一个音乐播放器2--歌词高亮滚动

作者站长头像
站长
· 阅读数 35

按照惯例,先上效果图:

写一个音乐播放器2--歌词高亮滚动

实现

书接上回,实现了进度条写一个音乐播放器1--歌曲播放进度条,现在来实现歌词布局与歌词随歌曲播放高亮滚动功能。

html部分

采用无序列表ulv-for实现歌词布局,一行一句歌词,默认中间行为当前播放歌词,高亮显示它。

<audio ref="player" autoplay ></audio> 

<div class="detail">   
    <div class="song-title">     
        <p ref="song">歌名</p>     
        <p ref="singer">歌手</p>   
    </div>   
    <div class="wrapper">     
        <ul ref="ul" class="content">     
            <li v-for="(item,index) of ms" :key=item.index>{{item.c}}</li>   
        </ul>   
    </div> 
</div>

scss样式部分

这里高亮当前播放歌词,采用动态样式绑定,lineHigh类为高亮样式。

.detailposition: absolute;   
    top1rem;   
    bottom2.6rem;   
    left0;   
    right0;   
    text-align: center;   
    color#26a2ff;    
    .song-title {    
        width100%;     
        height2rem;  
        p {      
            width100%;       
            line-height: .8rem;       
            font-size18px;       
            color#FFD700;        
            margin-top: .1rem;       
            text-align: center;
        }
    }
    .wrapper {    
        overflow: hidden;     
        position: absolute;     
        top2rem;     
        right0;     
        left0;     
        height545px;
        ul {      
            line-height32px;       
            width100%;       
            padding-bottom1rem; 
            li {        
                font-size16px;         
                transition-duration1200ms;  
            }
            .lineHigh {        
                color#FFD700;
            }
        }
    }
}

JS部分

布局完成,现在来实现给当前播放歌词绑定高亮lineHigh和随着歌曲播放向上滚动歌词。

高亮歌词

ms是按每行歌词存储改行歌词与改行歌词开始播放时间的数组;

lineNo为当前播放歌曲词行数,初始值为0

遍历歌词数组,判断歌词滚动时间是否等于当前歌词开始播放时间,

若是则lineNo+1,开始播放第一句,标记当前正在播放歌词;

给lineNo改行歌词加上lineHigh高亮样式。

data () {
    return {       
        lineNo0,
        Cpos7,       
        offset: -32,       
        ms: [],     
    }   
},      
mounted () {     
    const music = this.$refs.player  // 音频所在对象     
    const ulist = this.$refs.ul     
    const curTime = music.currentTime// 歌词滚动时间
    music.addEventListener('timeupdate'() => {      
        if(this.lineNo==this.ms.length)       return;
        const curTime = music.currentTime//播放器时间
        if(parseFloat(this.ms[this.lineNo].t) <= curTime){         
            this.lineHigh();//高亮当前行         
            this.lineNo++;       
        }     
    })          
    music.addEventListener('ended'() => {         
        this.goback(); //回滚歌词         
        music.play()     
    })      
}      

滚动歌词

Cpos为高亮屏幕中的第几行歌词,

Cpos这里设置为7,意在将高亮歌词置于屏幕中间位置;

offset为每行歌词高度,这里是每个li的高度为32px

当前歌词还没到第7行时,高亮改该行不用滚动歌词;

当歌词到达第7行之后,需向上滚动歌词,滚动距离为当前播放的歌词行数(lineNo-Cpos) * offset,

即为在播放第八行时,需要向上滚动一行,采用translateY实现向上滚动。

并且注意给歌词父盒子wrapper要设置属性overflow: hidden;隐藏歌词超出部分。

注意:向上滚动一行高亮当前行时需移出上一行的高亮样式。

methods: {     
    // 高亮歌词滚动事件    
    lineHigh() {       
        const ulist = this.$refs.ul
        const list = ulist.getElementsByTagName("li");
        if(this.lineNo>0){         
            list[this.lineNo-1].removeAttribute("class");//去掉上一行的高亮样式       
        }       
        list[this.lineNo].className = "lineHigh";//高亮显示当前行            
        //文字滚动       
        if(this.lineNo > this.Cpos){         
            ulist.style.transform = "translateY("+(this.lineNo-this.Cpos)*this.offset+"px)"//整体向上滚动一行高度       
         }     
     },          
     // 重新播放是歌词重置事件     
     goback() {       
         const ulist = this.$refs.ul
         document.querySelector(".lineHigh").removeAttribute("class");
         ulist.style.transform = "translateY(0)";       
         this.lineNo = 0//lineNo清零,重新播放     
     }, 
}

然后是播放结束,重新开始播放,重新开始播放调用audio的API play即可重新开始播放,重新回滚至歌词第一行,将lineNo重置为0

最后

至此,歌词随歌曲播放滚动高亮已完成,接下来就是将歌词滚动与进度条进度同步,敬请期待下一篇吧。

写一个音乐播放器2--歌词高亮滚动