我正在尝试实现一些不错的幻灯片9个图像。下面是指向沙盒的链接,代码:https://jsfiddle.net/gq5r5o8r/
问题是,如果我将鼠标悬停在左边的第一张幻灯片上,然后快速将光标移到右边的最后一张幻灯片上,图像就会挤在一起,离开原来的位置,在右边的最后一张幻灯片和容器边缘之间会出现一个空白。
构造是基于列表的,因此宽度是980px,活动“悬停”图片的宽度是640px,剩下的8个压缩图像的宽度是340px。
我想问题与此有关:
.wb_sliders_menu ul:hover li {
width: calc( 340px / 8 );
}
可以通过将第一个和最后一个滑动边以某种方式粘贴到容器的左右两侧来解决这个问题吗?
提前谢谢!
最佳答案
TL;博士
使用弹性框:
.wb_sliders_menu ul { display: flex; }
.wb_sliders_menu ul li:hover { flex: 100; }
.wb_sliders_menu ul li {
min-width: 42.5px; /* or calc(340px / 8) */
max-width: 640px;
flex: 1;
}
https://jsfiddle.net/g4nw310b/4/
为什么会这样?
问题似乎是,这些转变并不是同时结束的。
让我们看看数学。为了更简单,让我们假设一个线性转换(
y = x
)。另外,由于我是四舍五入的数字,数学上加起来不到100%,但足以得到这个想法。0.00秒
所有元素都以108.89px(980px/9)开始。其中8个将达到42.50px(340px/8)。另一个会达到980px。所有这些都需要0.5秒才能到达。这意味着收缩的速度将是
(42.50px-108.89px)/0.5s = -132.78px/s
。正在生长的将以(640px-108.89px)/0.5s = 1062.22px/s
的速度生长。如果你不移动鼠标,它们会保持这样的速度,这样会互相抵消,所以你看不到移动上的任何差异:(8 * -132.78px/s) + 1062.22px/s) = -.02 ≈ 0
。0.25秒
现在让我们向前移动0.25秒。一幅图像介于108.89px和640px之间(即374.44px),另一幅图像介于108.89px和42.50px之间(即75.70px)。那是
374.44px + (75.70px * 8) = 980px
。到现在为止,一直都还不错。。。现在假设您能够将鼠标从第一个图像即时移动到最后一个图像,同时将鼠标悬停在
ul
元素上。这将触发.wb_sliders_menu ul li:hover
来切换第一个和最后一个元素的宽度,分别切换到340px/8和640px,而其余元素保持不变。这将重置这两个元素的转换计时器,而其他元素仍保留在原始转换中。第一张图片现在从374.44px到42.50px,速率为
(42.50px-374.44px)/0.5s = -663.88px/s
。最后一张图像将以(640px-75.70px)/0.5s = 1128.60px/s
的速率从75.7px变为640px。其余的仍在最初的转变中,目前为75.7像素,以-132.78px/s
的速度从108.88像素上升到42.50像素。这给了我们(7 * -132.78px/s) + -663.88px/s + 1128.60px/s = -464.74px/s
的向量。哎呀-现在我们在退缩!0.50秒
再向前闪0.25秒。第一张图像现在在374.44像素和42.50像素(即208.47像素)之间。最后一张图像介于640px和75.70px(即357.85px)之间。其他7幅图像已经完成了转换,现在是42.50像素。这给了我们
208.47px + 357.85px + (42.50px * 7) = 863.82px
,在右边给了我们一个980px - 863.82px = 116.18px
的间隙。第一个和最后一个继续以
-663.88px/s
和1128.60px
的速率过渡,给了我们以前要弥补的464.72px/s ≈ 464.74px/s
。我们现在正在填补空白。0.75秒
再过0.25秒,以464.72px/s的速度,我们已经填补了之前的空白(
0.25s * 464.72px/s = 116.18px
),一切看起来都很好。我们怎么解决?
如果在0.25s标记处,中间的7张幻灯片将重置它们的转换,它们将以
(42.50-75.70px)/0.5s = -66.40px/s
的速率进行。在0.5s标记处,它们将介于75.70px和42.50px(即59.10px)之间。这给了我们一个新的和。它们仍将以互相抵消的速度过渡(208.47px + 357.85px + (59.1px * 7) = 980.02px ≈ 980px
)。最终,转换的速度需要相互抵消,以获得平滑的效果。可能最简单的方法是确保所有元素同时开始和结束,使用相同的计时函数。
Javascript
我们可以在Javascript中通过手动设置悬停类来实现这一点。然而,它也需要对css进行一些奇怪的调整。这里显示的JS代码使用jQuery,因为它更容易编写,但也可以用纯JS完成。
$(".wb_sliders_menu > ul").on("mouseenter mouseleave", "> li", function(e){
var $li = $(this);
var $ul = $li.parent();
if (e.type === "mouseleave") {
// Remove the hover class to reset everything to it's initial width
var $lis = $("> li", $ul);
$lis.removeClass("hover");
$ul.removeClass("hover");
} else {
// Wait until the next animation frame, then add back the classes.
// This will effectively reset the timer
requestAnimationFrame(function() {
$ul.addClass("hover");
$li.addClass("hover");
})
}
});
您需要更改以下css规则以使用
(7 * -66.40px/s) + -663.88px/s + 1128.60px/s = -0.08px/s ≈ 0px/s
而不是.hover
。.wb_sliders_menu ul.hover li { width: calc( 340px / 8 ); }
.wb_sliders_menu ul li.hover {width: 640px;}
有时最右边的项目会消失,因为它实际上是移动到第二行,因为它不适合在容器中。所以您需要添加以下css规则:
.wb_sliders_menu ul { white-space: nowrap; }
.wb_sliders_menu li { display: inline-block; float: none; }
最后,你会有一个奇怪的间隙,因为
:hover
显示了空白。要解决这个问题,您需要确保您有inline-block
而不是</li><li>
。下面是一个工作示例:https://jsfiddle.net/6zkfewga/1/
CSS
现在是有趣的部分。弹性盒子!不使用任何javascript的解决方案。
.wb_sliders_menu ul { display: flex; }
.wb_sliders_menu ul li:hover { flex: 100; }
.wb_sliders_menu ul li {
min-width: 42.5px; /* or calc(340px / 8) */
max-width: 640px;
flex: 1;
}
您可以去掉
</li> <li>
规则和.wb_sliders_menu ul:hover li
。下面是一个工作示例:https://jsfiddle.net/g4nw310b/4/
关于html - 图像 slider 过度滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36545368/