javascript - Vimeo 图像和 javascript

标签 javascript jquery twitter-bootstrap vimeo

所以我无法让我的缩略图系统正常工作。它从 vimeo 获取图像并将其放入 .所以我试着让它循环播放,因为这样看起来更好。

但我无法让它工作 :( 有人可以帮助我吗?

            <div class="row">
            <div class="col-sm-3"><img src="" id="img1" class="img-rounded" width="100%" height="200px"></img></div>
            <div class="col-sm-3"><img src="" id="img2" class="img-rounded" width="100%" height="200px"></img></div>
            <div class="col-sm-3"><img src="" id="img3" class="img-rounded" width="100%" height="200px"></img></div>
            <div class="col-sm-3"><img src="" id="img4" class="img-rounded" width="100%" height="200px"></img></div>
        </div>
        <br>
        <div class="row">
            <div class="col-sm-3"><img src="" id="img5" class="img-rounded" width="100%" height="200px"></img></div>
            <div class="col-sm-3"><img src="" id="img6" class="img-rounded" width="100%" height="200px"></img></div>
            <div class="col-sm-3"><img src="" id="img7" class="img-rounded" width="100%" height="200px"></img></div>
            <div class="col-sm-3"><img src="" id="img8" class="img-rounded" width="100%" height="200px"></img></div>
        </div>
    </div>
</body>

<script>
    var ids = ["169971394", "169657641", "169569693", "169569661", "169569619", "169569539", "169569509", "169566439"]
    var imgs= ["img1", "img2", "img3", "img4", "img5", "img6", "img7", "img8"]
    for (i = 0; i < 7; i++) {
        $(document).ready(function () {
            var vimeoVideoUrl = 'https://player.vimeo.com/video/' + ids[i];
            console.log(vimeoVideoUrl);
            var match = /vimeo.*\/(\d+)/i.exec(vimeoVideoUrl);
            if (match) {
                var vimeoVideoID = match[1];
                $.getJSON('http://www.vimeo.com/api/v2/video/' + vimeoVideoID + '.json?callback=?', { format: "json" }, function (data) {
                    featuredImg = data[0].thumbnail_large;
                    console.log(imgs[i]);
                    $(imgs[i]).attr("src", featuredImg);
                });
            }
        });
        }
</script>

(以上是重要部分。)仅供引用:我为此使用 Bootstrap 和 jquery。 (还有一些其他的,不过那些都不重要)

最佳答案

一些背景

在循环中执行此类操作的复杂之处在于 $.getJSON()异步,而 for 循环是同步 .要基本了解差异,请查看 this answer 。但这是总体思路:

同步:事物按顺序执行。当一个操作完成时,下一个操作开始。

例子:

var a = 0; // This is executed first
a = a + 1; // This is executed second

异步:同步操作不会等待异步操作完成后再继续执行脚本

例子:

// This is executed first
var a = 0;

// This is executed 2nd, but the function inside won't be called for 1 second
setTimeout(function() {
  // this is executed last, outputs 1
  console.log(a);
}, 1000);

// this is executed third, before the function call
a = a + 1;

你的问题

在您的示例代码中,您正在同步操作中执行异步函数。通常,这没关系,您真的不必担心。当您尝试在异步函数中使用变量 i,但变量 i 在同步操作期间 发生更改时,就会出现问题(for循环)。

这是一个显示正在发生的事情的例子

for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000)
}

思考一下

现在,通过查看代码,您可能希望它等待 1 秒,然后将每个数字记录到控制台,类似于

-> 0
-> 1
-> 2
-> 3
-> 4

收获

但是,如果您实际运行上面的代码片段,您会看到它每次都记录 5 。这是因为当回调函数实际运行时,变量 i 实际上的值为 5。

但是如何呢?

如何? for 循环在每个 setTimout() 完成之前继续执行,等待 1 秒。因此,到 1 秒结束时,循环已经将 i 递增到中断循环的点,在本例中为 5

在你的问题中,一个简单的 console.log(i); 在你的回调函数中很可能会显示 7 八次,因为变量 i 仍在递增,而您的 $.getJSON() 实际上正在等待返回结果。当结果实际返回时,循环可能已完成运行,i 将等于 7

解决方案

为了确保我们在页面上以正确的顺序放置视频和图像,并且我们实际上将每张图像放置在正确的位置,我们需要为这种异步行为做一些重要的变通办法。我对这段代码进行了注释,以便您了解每行代码的作用。

// dom is ready to be manipulated
$(document).ready(function() {
  // create an array of our video ids
  var ids = [
    "169971394",
    "169657641",
    "169569693",
    "169569661",
    "169569619",
    "169569539",
    "169569509",
    "169566439"
  ];
  // initialize an empty array that will eventually hold our videos
  var videos = [];
  // loop through our array of ids
  ids.forEach(function(id, i) {
    // because these are in order, ids[0] should be in #img1 etc
    var image = '#img' + (i + 1);

    // get your video url --not actually used in this code
    var vimeoVideoUrl = 'https://player.vimeo.com/video/' + id;

    // create an object that holds the information for this video that can
    // be gathered *synchronously*
    var v = {
      id: id,
      image: '#img' + (i + 1),
      video: vimeoVideoUrl
    };

    // add this object to our initially empty array
    videos.push(v);

    /* after the loop ends, videos array might look like this

    [
     {
       id: "169971394",
       image: "#img1",
       video: "https://player.vimeo.com/video/169971394"
     },
     {
       ... next video
     } ... for each video
    ]

    */
    // do our ajax operation to get the rest of the video information
    $.getJSON(
      'https://www.vimeo.com/api/v2/video/' + id + '.json?callback=?', {
        format: "json"
      },
      // REMEMBER -- this function is *asynchronous* and we can't trust the
      // value of the increment from our loop, so this is relatively complex
      function(data) {
        // get the id of the returned video
        var id = data[0].id;

        // get the thumbnail
        var thumb = data[0].thumbnail_large;

        // loop through our videos array
        videos.forEach(function(v, i) {
          // find the element of the array with the id that was just returned
          if (v.id == id) {
            // and add the thumbnail url to the object
            videos[i].thumbnail = thumb;

            /* an element of the videos array will look like this when the callback
               has finished for that video

            {
              id: "169971394",
              image: "#img1",
              video: "https://player.vimeo.com/video/169971394",
              thumbnail: "https://i.vimeocdn.com/video/574879586_640.jpg"
            }

              notice that the thumbnail property is now set
            */
          }
        });

        // each time we execute the callback, we need to know if it's the last 
        // execution, so we will need to check if every callback has been completed

        // this condition returns false if the thumbnail element is not assigned
        // to every object in the videos array, which would tell us that this isn't
        // the last execution of the callback
        if (videos.every(function(v) {
          return v.thumbnail !== undefined
        })) {
          // if this is the last execution of the callback,
          // loop through each item in the videos array
          videos.forEach(function(video) {
            // set the src of the video's corresponding image to the url of the thumbnail
            $(video.image).attr("src", video.thumbnail);
          });
        }
      }
    );
  });
});

https://jsfiddle.net/o82L6q48/2/ 实际操作

请注意,这可能比实际需要的更复杂,但它确实有效,我希望您能从中学到一些东西。

关于javascript - Vimeo 图像和 javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37728134/

相关文章:

javascript - Materialize.css 自动完成不适用于 Polymer

javascript - 为什么源 map 不起作用?

javascript - 在 SlickGrid 中保存更改

html - Bootstrap Navbar-right 错误

html - 移动设备上的 Twitter Bootstrap 未显示为 "xs"大小

javascript - 将 bootstrap carousel 保持为静态背景,顶部有文本

javascript - moveRight(num) 问题!

html - Bootstrap 的导航和页脚问题

javascript - 并排内联 block div,最后一个错误地在中间对齐

javascript - 为什么当用户点击太快时 jQuery Mobile Simple Dialogue 会卡住?