代码之家  ›  专栏  ›  技术社区  ›  Ellio_Smoov

使用通过自定义数据属性检索的选择器在音频播放上显示目标div

  •  2
  • Ellio_Smoov  · 技术社区  · 7 年前

    我有一个有几首歌的音频播放器。对于每首歌,我想显示一个 div 下面是特定歌曲的歌词,而隐藏了所有其他歌曲的歌词。

    这是音频播放器的脚本,它可以工作:

    initAudio($('#playlist li:first-child'));
    
    function initAudio(element){
        var song = element.attr('song');
        var title = element.text();
        var cover = element.attr('cover');
        var artist = element.attr('artist');
        var album = element.attr('album');
    
        //Create audio object
        audio = new Audio('public/songs/'+ song);
    
        //Insert audio info
        $('.artist').text(artist);
        $('.title').text(title);
        $('.album').text(album);
    
        //Insert song cover
        $('img.cover').attr('src','public/images/' + cover);
    
        $('#playlist li').removeClass('active');
        element.addClass('active');
    
        // Set timer to 0
        $('#duration').html('0:00');
    
        // Maintain volume on song change
        audio.volume = $('#volume').val() / 100;
    }
    

    这里是播放列表和歌词HTML的简化版本:

    <ul id="playlist">
        <li class="song-list active" song="song-1.wav" data-id="song-1"></li>
        <li class="song-list" song="song-2.wav" data-id="song-2"></li>
        <li class="song-list" song="song-3.wav" data-id="song-3"></li>
    </ul>
    
    <div id="song-1" class="lyrics">Lyrics to song 1</div>
    <div id="song-2" class="lyrics">Lyrics to song 2</div>
    <div id="song-3" class="lyrics">Lyrics to song 3</div>
    

    我试了很多东西,但都没有用。我甚至不知道如何在播放每首歌曲时定位以提取 data-attribute .

    有什么想法吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   user8217724 user8217724    7 年前
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Song List Sample</title>
        <script type="text/javascript" language="javascript" src="./scripts/jquery-3.2.1.min.js"></script>
    
        <script type="text/javascript" language="javascript">
    
            var audio = null;
    
            function initAudio(songElem) 
            {
                var songID = null;
                var title = null;
                var metaID = null;
                var songFile = null;
                var cover = null;
                var artist = null;
                var album = null;
    
                try 
                {
    
                    // Retrieve song Title and meta-data identifier
                    songID = "#" + songElem.getAttribute("id");
                    title = $(songID).text();
                    metaID = "#" + $(songID).attr('data-id');
    
                    // Get selected song data
                    songFile = $(metaID).attr('song');
                    cover = $(metaID).attr('cover');
                    artist = $(metaID).attr('artist');
                    album = $(metaID).attr('album');
    
                    // Update summary to be displayed
                    $("#currentTitle").text(title);
                    $("#currentAlbum").text(album);
                    $("#currentArtist").text(artist);
                    $("#currentCover img").attr("src", cover);
    
                    // Hide and display applicable song data
                    $(".songmeta").hide();
                    $("#currentSong").show();
                    $(metaID).show();
    
                    // Create or update audio object
                    if (audio != null) audio.src = songFile;
                    else audio = new Audio(songFile);
    
                    audio.play();
    
                    // Update current song selection
                    $(".songlist").attr("active", "false");
                    $(songID).attr("active", "true");
    
                }
                catch (e) 
                {
                    alert("initAudio Error:  " + e.Message);
                }
                finally 
                {
    
                }
    
            }
        </script>
    
    
    </head>
    <body>
    
    <ul id="playlist">
        <li id="s1" class="song-list" onclick="initAudio(this)" active="false" data-id="song-1">Song One</li>
        <li id="s2" class="song-list" onclick="initAudio(this)" active="false" data-id="song-2">Song Two</li>
        <li id="s3" class="song-list" onclick="initAudio(this)" active="false" data-id="song-3">Song Three</li>
    </ul>
    
    <div id="currentSong" >
    <table border="1">
    <tr>
    <td>
    <table border="1">
    <tr><td><b>Song</b></td><td id="currentTitle"></td></tr>
    <tr><td><b>Album</b></td><td id="currentAlbum"></td></tr>
    <tr><td><b>Artist</b></td><td id="currentArtist"></td></tr>
    </table>
    </td>
    <td id="currentCover"><img alt="" src="" /></td>
    </tr>
    </table>
    </div>
    
    <div id="song-1" class="songmeta" artist="Song 1 Artist" album="Song 1 Album" cover="./images/Album1.jpeg" song="./songs/Song1.mp3" >Lyrics to song 1</div>
    <div id="song-2" class="songmeta" artist="Song 2 Artist" album="Song 2 Album" cover="./images/Album2.jpeg" song="./songs/Song2.mp3" >Lyrics to song 2</div>
    <div id="song-3" class="songmeta" artist="Song 3 Artist" album="Song 3 Album" cover="./images/Album3.jpeg" song="./songs/Song3.mp3" >Lyrics to song 3</div>
    
    <script type="text/javascript" language="javascript">
        // Initialization
        $(".songmeta").hide();
        $("#currentSong").hide();
    </script>
    </body>
    </html>
    
        2
  •  0
  •   Axel    7 年前

    1. data-id -通过调用属性 element.attr('data-id')
      返回字符串“song-1”。
    2. 将DOM元素作为目标 id="song-1" 通过呼叫 $('#song-1') ;
      哪一个是 $('#' + element.attr('data-id')) (如果您不知道原因,请参阅步骤1)。
    3. 既然我们有了目标,我们应该提前隐藏所有其他歌词 $('.lyrics').hide() 只显示通缉犯 $('#' + element.attr('data-id')).show() .

    initAudio($('#playlist li:first-child'));
    
    function initAudio( element ) {
        // this version performs slightly better than the one in the 1, 2, 3 explanations
        $('.lyrics').hide().filter('#' + element.attr('data-id')).show()
    }
    
    $('#playlist').on('click', function( oEvent ) {
        initAudio( $( oEvent.target ) )
    } );
    <ul id="playlist">
        <li class="song-list active" song="song-1.wav" data-id="song-1">Click Me 1!</li>
        <li class="song-list" song="song-2.wav" data-id="song-2">Click Me 2!</li>
        <li class="song-list" song="song-3.wav" data-id="song-3">Click Me 3!</li>
    </ul>
    
    <div id="song-1" class="lyrics">Lyrics to song 1</div>
    <div id="song-2" class="lyrics">Lyrics to song 2</div>
    <div id="song-3" class="lyrics">Lyrics to song 3</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    这就像你希望的那样(至少我希望如此),但不是一个理想的解决方案;只是想解释一下发生了什么!上述解决方案的缺点是需要大量不必要的计算。

    //initAudio($('#playlist li:first-child'));
    initAudio($('#playlist').find('li:first-child')); // performs better
    
    function initAudio( element ) {
        // if you chain it this way you don't have to cache $('.lyrics')
        $('.lyrics') // get collection of all div.lyrics
            .filter('.active').removeClass('active') // target the current div.lyrics.active and remove class "active"
                .end() // get collection div.lyrics back again
                    .filter('#' + element.attr('data-id')).addClass('active'); // filter target div.lyrics#song-[1|2|3] and add class "active"
    }
    
    $('#playlist').on('click', function( oEvent ) {
        initAudio( $( oEvent.target ) )
    } );
    .lyrics { /* this will prevent to show all lyrics before you call initAudio() */
        display: none;
    }
    .lyrics.active { /* style active lyrics as you like */
        display: initial;
    }
    <ul id="playlist">
        <li class="song-list active" song="song-1.wav" data-id="song-1">Click Me 1!</li>
        <li class="song-list" song="song-2.wav" data-id="song-2">Click Me 2!</li>
        <li class="song-list" song="song-3.wav" data-id="song-3">Click Me 3!</li>
    </ul>
    
    <!-- set one as active in advance if you like -->
    <div id="song-1" class="lyrics active">Lyrics to song 1</div>
    <div id="song-2" class="lyrics">Lyrics to song 2</div>
    <div id="song-3" class="lyrics">Lyrics to song 3</div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    额外重新组合

    要在使用自定义HTML5属性时保持有效标记,只需在属性前面加上 data-

    所以考虑改变

    song="song-#.wav"
    

    data-song="song-#.wav"
    

    cover data-cover , artist data-artist 等)。



    额外的灵感

    根据您构建站点的方式,还有比使用 data-*

    为什么不把数据从实际的HTML中分离出来呢。为此,您可以将数据作为变量进行部署。

    var sIdCurrent = undefined,
        oData = {
        'song-1': { artist: 'artist 1', lyrics: 'Lyrics to song 1' },
        'song-2': { artist: 'artist 2', lyrics: 'Lyrics to song 2' },
        'song-3': { artist: 'artist 3', lyrics: 'Lyrics to song 3' },
    };
    
    function initAudio( sId ) {
    
        if ( sId === sIdCurrent ) return;
        sIdCurrent = sId;
        //$('#artist').find('span').text( oData[ sId ].artist );
        //$('#lyrics').find('span').text( oData[ sId ].lyrics );
        // the above can be abstracted to
        for ( sKey in oData[ sId ] ) {
            $('#' + sKey).find('span').text( oData[ sId ][ sKey ] );
        }
    
    }
    
    initAudio('song-1');
    
    $('#playlist').on('click', function( oEvent ) {
        initAudio( oEvent.target.id )
    } );
    <!-- As you can see the markup is much cleaner now.
         No need to store data uneffectively in markup. -->
    
    <ul id="playlist">
        <li class="song-list active" id="song-1">Click Me 1!</li>
        <li class="song-list" id="song-2">Click Me 2!</li>
        <li class="song-list" id="song-3">Click Me 3!</li>
    </ul>
    
    <div id="artist">Artist: <span><span></div>
    <div id="lyrics">Lyrics: <span><span></div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>