在 div 内创建移动图像循环



我想建立一个这样的图片库,其中图片会自动循环播放,但同时,也可以使用鼠标滚轮通过图库进行交互。我还会实现这样的效果,即图像而不是滚动屏幕在侧面收缩。

所以我试图了解从哪里开始,但我找不到任何用于该任务的库,所以我从头开始尝试使用香草 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;
  • 具有类似于上述循环函数的循环功能,但iflast复制与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>

最新更新