Play HTML5 video from JSON file using next and prev buttons

拜拜、爱过 提交于 2019-12-13 02:51:51

问题


I have JSON file which contains video data eg video title and video link.

Here is jsffiddle:demo

Here is a JSON file sample:

[{

        "title": "How to create video?",
        "link": "https://storage.googleapis.com/coverr-main/mp4/Sunset-Desert-Run.mp4"
    },

    {
        "title": "How to add audio?",
        "link": "https://app.coverr.co/s3/mp4/Sand-Slow-Walk.mp4"
    },
    {
        "title": "How to add music?",
        "link": "https://app.coverr.co/s3/mp4/Steaming-Yellowstone.mp4"
    },
    {
        "title": "How to add scene?",
        "link": "https://app.coverr.co/s3/mp4/Skater-in-the-Park.mp4"
    },
    {
        "title": "How to preview a video?",
        "link": "https://app.coverr.co/s3/mp4/Stop-Sign.mp4"
    },
    {
        "title": "How to delete video?",
        "link": "https://app.coverr.co/s3/mp4/RV-Park.mp4"
    }
]*

I want when the user clicks a prev button it should play the previous video and display video title too if the user clicks next button it should play the next video and display video title too. here is visual how it looks.

here is what I have tried so far.

HTML

        <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<div id="video-container">

<h1 class="movie-title">Movie title</h1>

   <video class="videoplayer" id="video-player_transformed"
                            playsinline autoplay muted>
 <source src="https://app.coverr.co/s3/mp4/Sand-Slow-Walk.mp4"
                                type="video/mp4">

   </video>

</div>

<div class="btns">
    <div class="prev">
           Prev
   </div>

   <div class="next">
           next
   </div>
 </div>

Here is CSS

body{
  background: gray;
}
#video-container{
position: relative;
  height: 314px;
  width: 800px;
  display: flex;
  justify-content: center;
   align-self: center;
   overflow: hidden;
}
.movie-title{
position: absolute;
top: 0px;
}

.btns{
  display: flex;
  justify-content: center;
}
.prev, .next{
  display: flex;
  width: 100px;
  height: 50px;
  background: red;
  margin: 20px;
    justify-content: center;
    align-items: center;
    color: white;
    cursor: pointer;
}
video{
height: 400px;
width: 400px;
}

Here is JS

$(document).ready(function () {

      var myData;

            $.ajax({
              dataType: 'json',
              url: 'https://videomill-bot.audiencevideo.com/videoexplainer/videoexplainer/data/video.json',
              data: myData,
              success: function(data) {
                console.log($('.videoplayer').append(myData));
        myData = myData;

              },
            })


var player = document.querySelector('#videoplayer');
var i = 0;
var prev = document.querySelector('.prev');
var next = document.querySelector('.next');

prev.addEventListener('click',function(){
    player.src = myData[i == 0 ? myData.length-- : i--];
    video.play();
},false);

next.addEventListener('click',function(){
    player.src = myData[i ==myData.length-- ? 0 : i++];
    video.play();
},false);

player.src = myData[i];
player.play(); //init the video player


});

Unfortunately, I am getting the following error after clicking buttons next or prev.

Uncaught TypeError: Cannot read property 'length' of undefined

What do I need to change to get what I want? any help or suggestion will be apreciated thanks.


回答1:


Your issue is because the code after the .ajax() request is running before the request has completed, meaning the myData variable has no accessible data.

To solve this you could try something like the modified example below.

(function($) {
    'use strict';

    /**
     * Ajax response data will be stored in this local variable
     * @var    {Array}
     */
    var myData = [];

    /**
     * jQuery video element
     * @var    {Object}
     */
    var $player = $('video.videoplayer');

    /**
     * jQuery movie title element
     * @var    {Object}
     */
    var $title = $('.movie-title');

    /**
     * jQuery previous button element
     * @var    {Object}
     */
    var $prev = $('.prev');

    /**
     * jQuery next button element
     * @var    {Object}
     */
    var $next = $('.next');

    /**
     * Custom jQuery function to add sources to a media element
     * @param    {Array|String}    sources
     */
    $.fn.setSource = function(sources) {

        // Get the media tag (video/audio)
        var tag = this.prop('tagName').toLowerCase();

        // Clear any existing sources
        this.empty();

        // Check if sources paramater is an array
        if (Array.isArray(sources)) {

            // Loop through each source
            for (let i = 0; i < sources.length; i++) {
                var src = sources[i];
                var type = /(?:\.([^.]+))?$/.exec(src); // Get file extention (.mp4, .ogv, .webm etc)

                if (type[0]) {
                    type = type[0].replace('.', '');
                }
                // Create and append a source tag
                this.append($('<source>', {
                    src: src,
                    type: tag + '/' + type
                }));
            }
        } else {
            this.attr('src', sources);
        }
    };

    /**
     * Reusable function to update player element
     * @param    {Object}    data    Expects an object with `link` and `title` attributes
     */
    function updatePlayer(data) {
        $player.setSource(data.link); // Set the video source
        $title.text(data.title); // Add the title
    }

    // Disable actions because we have no data
    $prev.prop('disabled', true);
    $next.prop('disabled', true);

    // Send request to server to recieve data
    $.ajax({
        dataType: 'json',
        url: 'https://videomill-bot.audiencevideo.com/videoexplainer/videoexplainer/data/video.json'
    }).then(function(data) {
        myData = data; // replace `myData` with the ajax response data

        // Check if we have data
        if (myData && myData.length) {

            // Re-enable actions because we have data
            $prev.prop('disabled', false);
            $next.prop('disabled', false);

            updatePlayer(data); // Set the video source (see functions above)
            $player.get(0).play(); // Play the html5 video*
            // *Most browsers will not allow playing without any user interaction
        }

    }).fail(function(error) {
        // Request failed, inform user
        alert('There was an error downloading videos, please refresh and try again.');
        console.warn(error);
    });

    // On click set video element to PREVIOUS video in myData
    $prev.on('click', function() {

        // Check if we have data before attempting to access it
        if (myData && myData.length) {
            updatePlayer(myData[i === 0 ? myData.length - 1 : --i]);
            $player.get(0).play();
        }

        // Prevent default click action
        return false;
    });

    // On click set video element to NEXT video in myData
    $next.on('click', function() {

        // Check if we have data before attempting to access it
        if (myData && myData.length) {
            updatePlayer(myData[i === myData.length - 1 ? 0 : ++i]);
            $player.get(0).play();
        }

        // Prevent default click action
        return false;
    });

})(jQuery || window.jQuery);

(this hasn't been tested and there are many ways to achieve what you are aiming to do but it should give you an idea of where to start.)

A few things to note:

  • You are using jQuery so I have updated element selectors to make the most out of it.
  • In your ajax success function you we're redefining myData as its self and not with the response data (myData = myData changed to myData = data)
  • I have created functions to try and mitigate code duplication.
  • Finally, be careful autoplaying media elements with javascript as browser restrictions apply.


来源:https://stackoverflow.com/questions/55670451/play-html5-video-from-json-file-using-next-and-prev-buttons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!