音頻——H5 audio


分享站又有新功能了:將文件站上的語音文件正確播放出來。效果圖:

    8888

暫停:

           1

播放:

           2

實現的效果:類似於音樂播放器一般,但是較之更簡單一些,可以正常播放語音,有拖動、快進后退效果便可。

思路:

首先想到的便是利用H5中的audio標簽來實現

<audio> 標簽定義聲音,比如音樂或其他音頻流。

可是最終卻發現原始的H5標簽播放的音頻效果,有點太牽強,其美觀程度遠遠達不到我們預期的,於是只能摒棄這樣的想法,另辟蹊徑了。最終想到最完美的解決方案依舊是利用H5的audio標簽,但是得重新定義它的滾動條以及前進、快退等事件。

參考資料:

HTML  <audio>標簽 http://www.w3school.com.cn/tags/tag_audio.asp

HTML 5 視頻/音頻參考手冊 http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp

拜讀:https://segmentfault.com/a/1190000007332028

主要代碼:


<div class="container">
    <div class="starter-template">
        <h1>{{data.title}}</h1>
        <div class="vicoebox">
            <div class="vicoebox-img">
                <a href="javascript:void(0)" onclick="audioplay()" class="btn-play"></a>
                <img src="{{imgSiteUrl}}{{img}}" width="190" height="190"/>
            </div>
            <audio id="audio" preload type="audio/mpeg" src="{{imgSiteUrl}}{{data.content}}"></audio>
            <!-- 語音控制模塊開始 -->
            <div class="g-panel">
                <div class="m-progress m-progress-song">
                    <div id="songprogress" class="progress"></div>
                    <div id="songbar" class="progressbar"></div>
                    <ul class="songtime">
                        <li class="start" id="start">0:00</li>
                        <li class="end" id="end">0:00</li>
                    </ul>
                </div>
            </div>
        </div>
        <!-- 語音控制模塊結束 -->
    </div>
</div>

           3

js:

<script type="text/javascript">
    jQuery('.btn-play').click(function () {
        if (jQuery(this).hasClass("btn-play")) {
            audio.play();
            jQuery(this).removeClass('btn-play').addClass('btn-pause');
        } else {
            audio.pause();
            jQuery(this).removeClass('btn-pause').addClass('btn-play');
        }
    });

    //---------------------------------工具方法開始
    var Util = function () {
        // 格式化時間為分:秒的形式
        function formatTime(seconds, curS) {
            var totalS = parseInt(seconds);
            var minute = Math.floor((totalS / 60));
            var second = totalS - minute * 60;
            second = second < 10 ? ("0" + second) : second;
            return minute + ":" + second;
        }

        // 將時間轉化為百分比
        function timeToPercent(curS, totalS) {
            var percent = parseInt((Number(curS) / Number(totalS)) * 100) + "%";
            return percent;
        }

        // 更新時間
        function updateTime(dom, seconds) {
            var result = formatTime(seconds);
            dom.html(result);
        }

        // 更新進度條
        function updateProgress(dom, percent) {
            dom.css("width", percent);
            return true;
        }

        // 更新進度滑塊
        function updateBarPos(dom, percent) {
            dom.css("left", percent);
            return true;
        }

        return {
            formatTime: formatTime,
            updateTime: updateTime,
            updateProgress: updateProgress,
            updateBarPos: updateBarPos,
            timeToPercent: timeToPercent,
        };
    }();
    //---------------------------------工具方法結束

    //更新結束時間
    jQuery("#audio")[0].addEventListener("loadedmetadata", function () {
        duration = this.duration;//獲取總時長
        formatDuration = Util.formatTime(duration);
        jQuery('.end').html(formatDuration);
    });

    function audioplay() {
        var audio = jQuery("#audio")[0];
        var start = jQuery('.start');//開始時間
        var end = jQuery('.end');//結束時間

        var sprocontainer = jQuery(".m-progress-song");//歌曲進度條容器
        var sProgress = jQuery("#songprogress");
        var songbar = jQuery("#songbar");//歌曲進度條滑塊


        // 監聽歌曲播放時間發生變化事件
        audio.addEventListener("timeupdate", function () {
            var curS = audio.currentTime;
            var duration = audio.duration;
            var curPercent = Util.timeToPercent(curS, duration);

            // 更新歌曲時間,進度條
            Util.updateTime(start, curS);//更新開始時間
            Util.updateProgress(sProgress, curPercent);
            Util.updateBarPos(songbar, curPercent);
        });

        //歌曲進度條滑塊滑動事件
        songbar.on("touchstart", function (e) {
            e.preventDefault();
            e.stopPropagation();

            jQuery(audio).off("timeupdate");
            audio.pause();

            var totalW = jQuery(sprocontainer).width(); //播放條容器總長度
            var leftDis = jQuery(sProgress).offset().left;
            var curS = 0;
            var curPercent = 0;
            var percent = "";
            var touchMove = e.originalEvent.changedTouches[0].clientX;
            var dis = e.originalEvent.changedTouches[0].clientX - leftDis;
            songbar.on("touchmove", function (e) {//當觸點在觸控平面上移動時觸發touchmove事件
                e.preventDefault();
                e.stopPropagation();
                touchMove = e.originalEvent.targetTouches[0].clientX;
                dis = touchMove - leftDis > totalW ? totalW : touchMove - leftDis;
                dis = touchMove - leftDis < 0 ? 0 : dis;
                percent = Math.floor(dis / totalW * 100) + "%";
                Util.updateProgress(sProgress, percent);
                Util.updateBarPos(songbar, percent);

            });
            songbar.on("touchend", function (e) {//當手指從屏幕上離開的時候觸發
                e.preventDefault();
                e.stopPropagation();
                if (audio.paused) {
                    audio.play();
                    jQuery('.btn-play').removeClass('btn-play').addClass('btn-pause');
                }

                percent = Math.floor(dis / totalW * 100) + "%";
                Util.updateProgress(sProgress, percent);
                Util.updateBarPos(songbar, percent);
                duration = audio.duration;
                curS = duration * parseInt(percent.replace("%", "")) / 100;
                audio.currentTime = curS;

                audio.ontimeupdate = function () {
                    var curS = audio.currentTime;
                    var curPercent = Util.timeToPercent(curS, duration);

                    // 更新歌曲時間,進度條
                    Util.updateTime(start, curS);
                    Util.updateProgress(sProgress, curPercent);
                    Util.updateBarPos(songbar, curPercent);
                };
                songbar.off("touchmove touchend");
            });
        });

        // 歌曲進度條點擊事件
        sprocontainer.on("mousedown", function (e) {
            var totalW = jQuery(sprocontainer).width();
            var leftDis = jQuery(sProgress).offset().left;
            var curS = 0;
            var curPercent = 0;
            var dis = e.pageX - leftDis > totalW ? totalW : e.pageX - leftDis;
            percent = Math.floor(dis / totalW * 100) + "%";

            sprocontainer.on("mouseup", function (e) {
                Util.updateProgress(sProgress, percent);
                Util.updateBarPos(songbar, percent);
                duration = audio.duration;
                curS = duration * parseInt(percent.replace("%", "")) / 100;
                audio.currentTime = curS;

                audio.ontimeupdate = function () {
                    var curS = audio.currentTime;
                    var curPercent = Util.timeToPercent(curS, duration);

                    // 更新歌曲時間,進度條
                    Util.updateTime(start, curS);
                    Util.updateProgress(sProgress, curPercent);
                    Util.updateBarPos(songbar, curPercent);
                };
                sprocontainer.off("mouseup");
            });

        });

        // 歌曲播放完畢事件
        audio.onended = function() {
            jQuery('.btn-pause').removeClass('btn-pause').addClass('btn-play');
        };
    }
</script>

遇到的問題:

1.duration 獲取歌曲的總時間:H5中有獲取duration的方法,基本在音頻播放的事件里,此屬性起到了至關重要的作用;

2.移動端的觸摸事件:touchstart、touchend、touchmove:

touchstart事件:當手指觸摸屏幕時候觸發,即使已經有一個手指放在屏幕上也會觸發;

touchmove事件:當手指在屏幕上滑動的時候連續地觸發。在這個事件發生期間,調用preventDefault()事件可以阻止滾動;

touchend事件:當手指從屏幕上離開的時候觸發。

而每個Touch對象包含的屬性如下;

clientX:觸摸目標在視口中的x坐標;

clientY:觸摸目標在視口中的y坐標;

identifier:標識觸摸的唯一ID;

pageX:觸摸目標在頁面中的x坐標;

pageY:觸摸目標在頁面中的y坐標;

screenX:觸摸目標在屏幕中的x坐標;

screenY:觸摸目標在屏幕中的y坐標;

target:觸目的DOM節點目標。

關於這三個事件,其實挺有意思的:雖然自己之前很少接觸過移動端的開發,但是總是被身邊同事的各種“神技能”震撼到,而當自己真的將別人手中的“神技能”實現時,還是挺有成就感的,總感覺一切就是那樣神奇(哈哈……這也是為什么喜歡這份工作的原因,樂在其中。);

3.鼠標事件中的mousedown、mouseup(這兩種事件見得次數多了,也便不贅述了)。

滴答滴答前進中:

樂在其中,還需要永不止步。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM