微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 div 让我们走得更远

如何解决在 div 让我们走得更远

我想构建一个this 这样的图片库,其中图片自动循环播放,但同时,也可以使用鼠标滚轮通过图库进行交互。我也会实现类似图像的效果,而不是从屏幕滚动到一边缩小。

所以我试图了解从哪里开始,但我找不到任何用于该任务的库,所以我从头开始尝试使用 vanilla js,这是我的尝试。

var testArray = document.querySelectorAll(".image");
var totImg = testArray.length;

var contIterazioni = 0;
var test = testArray[contIterazioni];
var bounding = test.getBoundingClientRect();



 function LoopFunction() {
     setInterval(galleryScroll,20);
 }
 function galleryScroll() {
     test = testArray[contIterazioni];
     bounding = test.getBoundingClientRect();
     if (bounding.left == 0) {
      //console.log("immagine bordo sx");
      if (test.width > 0) {
        test.width = test.width - .25;
      } else {
        contIterazioni = contIterazioni + 1;
        if (contIterazioni >= totImg){
          contIterazioni = 0;
        }
      } 
    }
 }

LoopFunction();
body{
  margin: 0;
  padding: 0;
  Box-sizing: border-Box;
}
.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  overflow: hidden;
}
<div class="container">
  <img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
  <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
  <img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
  <img src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="" class="image">
  <img src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="" class="image">
  
</div>

不幸的是,我不知道如何循环图像。你能帮我理解怎么做吗?你认为我的方法可以是一个好的方法吗?或者您会推荐其他方法来获得这种效果吗?

谢谢!

解决方法

在浏览所有图像时使用 for 循环将其宽度设置为初始值。还可以从轮播开始处添加额外的三张图片,以便结束时不会有空白。

    var testArray = document.querySelectorAll(".image");
    var totImg = testArray.length;

    var contIterazioni = 0;
    var test = testArray[contIterazioni];
    var bounding = test.getBoundingClientRect();

     var imgsWidths = []
     window.onload = () => {
       for(i = 0; i < testArray.length; i++) {
           imgsWidths[i] = testArray[i].width
       }
    }
     
   function galleryScroll() {
       test = testArray[contIterazioni];
       bounding = test.getBoundingClientRect();
       if (bounding.left == 0) {
        if (test.width > 0) {
          test.width = test.width - 2;
        } else {
          contIterazioni = contIterazioni + 1;
          if (contIterazioni >= totImg - 3){
            for(i = 0; i < testArray.length; i++) {
              testArray[i].width = imgsWidths[i]
            }
            contIterazioni = 0;
          }
        } 
      }
     window.requestAnimationFrame(galleryScroll)
     }

    window.requestAnimationFrame(galleryScroll);
body{
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    .container {
      width: 100vw;
      height: 100vh;
      display: flex;
      overflow: hidden;
    }
<div class="container">
      <img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
      <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
      <img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
      <img src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="" class="image">
      <img src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="" class="image">
      <img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
      <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
      <img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
    </div>

,

在保持相同的方法的同时,这应该与您提供的示例类似。如果您希望幻灯片保持其宽度,则所有图像都应具有相同的宽度。您的错误是没有将消失的图像添加回容器,最后并具有原始宽度,或者在这种情况下再次扩展。

// From https://www.javascripttutorial.net/javascript-queue/

function Queue() {
  this.elements = [];
}

Queue.prototype.enqueue = function(e) {
  this.elements.push(e);
};

Queue.prototype.dequeue = function() {
  return this.elements.shift();
};

Queue.prototype.isEmpty = function() {
  return this.elements.length == 0;
};

Queue.prototype.peek = function() {
  return !this.isEmpty() ? this.elements[0] : undefined;
};

Queue.prototype.length = function() {
  return this.elements.length;
}

let images = new Queue();

document.querySelectorAll(".image").forEach(img => images.enqueue(img));


var totImg = images.length();

var first = images.dequeue();
var last;

var firstWidth = first.width;
var lastWidth = 0.0;


var bounding = first.getBoundingClientRect();

var originalWidth = first.width;
var lastOriginalWidth = 0.0;

var step = 1.0;
var lastStep = 0.0;


function LoopFunction() {
  setInterval(galleryScroll,20);
}

function galleryScroll() {
  bounding = first.getBoundingClientRect();

  if (bounding.left == 0) {
    //console.log("immagine bordo sx");
    if (first.width > 0) {
      firstWidth -= step;
      if (firstWidth < 0) {
        firstWidth = 0;
      }
      first.style.width = firstWidth + 'px';
    } else {
      if (last && last.width != lastOriginalWidth) {
        last.width = lastOriginalWidth;
      }

      let container = document.querySelector('.container');
      container.removeChild(first);

      last = first;
      lastOriginalWidth = originalWidth;
      last.width = 0.0;
      lastWidth = 0.0;

      images.enqueue(last);
      container.appendChild(last);

      first = images.dequeue();
      originalWidth = first.width;
      firstWidth = originalWidth;
      lastStep = step * lastOriginalWidth / originalWidth;
    }
  }

  if (last && last.width <= lastOriginalWidth) {
    lastWidth += lastStep;
    last.style.width = lastWidth + 'px';
    if (last.width > lastOriginalWidth) {
      last.width = lastOriginalWidth;
    }
  }
}

LoopFunction();
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  overflow: hidden;
}
<div class="container">
  <img src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="" class="image">
  <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="" class="image">
  <img src="https://static.scientificamerican.com/sciam/cache/file/92E141F8-36E4-4331-BB2EE42AC8674DD3_source.jpg" alt="" class="image">
  <img src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="" class="image">
  <img src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="" class="image">

</div>

更新 #1

根据 OP 的要求,以下是我所做更改的进一步说明:

  • 我使用了 javascripttutorial 中的一个简单队列来获得反映目标的数据结构,即图像从右向左移动,一旦它们“退出”场景,就可以再次入队。

  • 遵循这个概念,我们需要指向队列头部和尾部的指针来更新它们的动画,特别是分别使用了firstfirstWidthoriginalWidth指向头部,在动画期间跟踪其当前宽度以及重新进入场景时应返回的原始宽度。同样,这也适用于 last

  • 一旦到位,我们的循环将由两部分组成,一部分处理头部动画并在头部图像到达 width == 0 时移动队列中的图像,另一部分处理尾部重新进入现场并扩大。为了实现连续性,我们在拥有新队列后使用一个简单的比例:step : originalWidth = lastStep : lastOriginalWidth,我们用它来确定每一帧头部和尾部图像分别压缩和扩展了多少。由于 step 是一个固定参数,lastStep 很容易通过简单的算术计算:lastStep = step * lastOriginalWidth / originalWidth

  • 代码:

      let container = document.querySelector('.container');
      container.removeChild(first);

      last = first;
      lastOriginalWidth = originalWidth;
      last.width = 0.0;
      lastWidth = 0.0;

      images.enqueue(last);
      container.appendChild(last);

      first = images.dequeue();
      originalWidth = first.width;

只是改变队列的上下文切换,其中指针和相应的数据得到更新以反映数据结构的变化。因此 first 变为 last,队列中的下一个图像是新的压缩 first,因此 originalWidth 移位。

让我们走得更远

现在,要实现您想要的实现,这仍然需要一些工作。首先,队列应该只反映实际的轮播,而不是你拥有的所有图像,所以理想情况下,你应该有一个包含所有图像和相应元数据的第一个静态数据结构,在这种情况下,我们主要需要它们的原始宽度。那么你就会有一个队列来表示正在制作动画的图像。

现在,您可以重用此代码并将图像的宽度更改为全部相等并适合您用于动画的视口,这应该可以正常工作。另一种选择是将头部图像的代码镜像到尾部,有一个固定的步长,所以当头部压缩 step 像素时,尾部扩展相同的 step 像素,当尾部达到最大宽度,在队列末尾引入一个新图像,成为新的尾部。

为了更详细地了解最后一个,算法看起来像这样:

  • 用它们各自的宽度(imgList)初始化图像容器的静态列表;
  • 初始化一个空队列(imgQueue);
  • 初始化指向队列中引入的最后一个图像的指针(listPtr);
  • 获取轮播应填充的视口的宽度 (vpWidth);
  • 当您还没有填满这样的宽度时,继续向队列中添加图像并在 listPtr 中向左移动 imgList
  • 具有与上述类似的循环功能,但 if 上的 last 复制了与 first 相似的步骤;

这应该就是一切了,我将在一段时间内处理代码,现在我需要休息一下;)

更新 #2

好的!制定出一些实际工作得体的东西。如果您有任何建议,请告诉我,同时,这里是:

// From https://www.javascripttutorial.net/javascript-queue/
function Queue() {
  this.elements = [];
}
Queue.prototype.enqueue = function(e) {
  this.elements.push(e);
};
Queue.prototype.dequeue = function() {
  return this.elements.shift();
};
Queue.prototype.isEmpty = function() {
  return this.elements.length == 0;
};
Queue.prototype.first = function() {
  return !this.isEmpty() ? this.elements[0] : undefined;
};
Queue.prototype.length = function() {
  return this.elements.length;
};
// Added function to peek last element in queue
Queue.prototype.last = function() {
  return !this.isEmpty() ? this.elements[this.elements.length - 1] : undefined;
};
// Added function that pops the head,enqueues it and returns it
Queue.prototype.shift = function() {
  const head = this.dequeue();
  this.enqueue(head);
  return head;
}

// Returns a queue of HTMLElements based on the given class
function loadQueue(className) {
  const rQueue = new Queue();
  document.querySelectorAll('.' + className).forEach(image => rQueue.enqueue(image));
  return rQueue;
}

// Queue of images to be added to the animation queue
const imgQueue = loadQueue('image');
// Images being animated inside the div
const imgAnimQueue = new Queue();

// To limit calls to the carousel
const carousel = $('.container');

function init() {

  // Width of the viewport being used for the animation
  // TODO: this shoud update whenever the page is resized,or at least the div
  const vpWidth = carousel.width();

  // Keeps track of the width of the images added to the animation queue
  var currentFilledWidth = 0;

  // Now that we have loaded the static information,let's clear the div
  // that will be used as carousel,so that we can add the correct number
  // of images back in
  carousel.empty();

  // Filling the animation queue
  while (currentFilledWidth < vpWidth) {
    // In order not to change the static data,we clone the image HTMLElement
    const img = $(imgQueue.shift()).clone();
    // Enqueuing the new image in the animation queue
    imgAnimQueue.enqueue(img);
    // Adding this image into the carousel
    img.appendTo(carousel);
    currentFilledWidth = currentFilledWidth + img.width();

    // If we overflow the carousel width,we set the tail image to fill
    if (currentFilledWidth > vpWidth) {
      const overflow = currentFilledWidth - vpWidth;
      img.width(img.width() - overflow);
      currentFilledWidth -= overflow;
    }
  }

  const step = 1;
  var firstWidth = imgAnimQueue.first().width();
  var lastWidth = imgAnimQueue.last().width();

  // Now the loop can start
  window.requestAnimationFrame(animateCarousel);

  // Main function that animates the carousel
  function animateCarousel() {
    let first = imgAnimQueue.first();
    let last = imgAnimQueue.last();

    // If the image is still not disappeared,keep compressing it
    if (firstWidth > 0) {
      firstWidth -= step;
      if (firstWidth < 0) firstWidth = 0;
      first.width(firstWidth);
      // Otherwise,remove it from the carousel and update all the data structs
    } else {
      first.remove();
      imgAnimQueue.dequeue();

      if (imgAnimQueue.first() != last) {
        first = imgAnimQueue.first();
        firstWidth = first.width();
      } else {
        first = last;
        firstWidth = lastWidth;

        imgAnimQueue.enqueue($(imgQueue.shift()).clone());
        last = imgAnimQueue.last();
        lastWidth = last.width();
        last.appendTo(carousel);
      }
    }

    if (lastWidth <= last.attr("data-original-width")) {
      lastWidth += step;
      // The image has completely expanded,let's introduce the next one
      if (lastWidth >= last.attr("data-original-width")) {
        last.width(last.attr("data-original-width"));
        imgAnimQueue.enqueue($(imgQueue.shift()).clone());

        last = imgAnimQueue.last();
        last.width(0);
        lastWidth = last.width();
        last.appendTo(carousel);
        // Otherwise just keep expanding it
      } else {
        last.width(lastWidth);
      }
    }

    window.requestAnimationFrame(animateCarousel);
  }
}
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  width: 100vw;
  height: 100vh;
  display: flex;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
  var loadedImages = 0;
  const count = 4;

  function loadImage(img) {
    if (loadedImages != count) {
      $(img).attr("data-original-width",$(img).width());
      loadedImages += 1;
      if (loadedImages == count) init();
    }
  }

</script>

<div class="container">
  <img onload="loadImage(this)" src="https://media-cdn.tripadvisor.com/media/photo-s/0e/eb/ad/3d/crazy-cat-cafe.jpg" alt="1" class="image">
  <img onload="loadImage(this)" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Chairman_Meow_Bao.jpg/1200px-Chairman_Meow_Bao.jpg" alt="2" class="image">
  <img onload="loadImage(this)" src="https://cdn.britannica.com/91/181391-050-1DA18304/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="3" class="image">
  <img onload="loadImage(this)" src="https://www.orlandocatcafe.com/wp-content/uploads/2020/07/14.png" alt="4" class="image">
</div>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。