【问题标题】:Multiple Image Transition on Hover悬停时的多个图像过渡
【发布时间】:2019-01-30 08:43:01
【问题描述】:

代码

我有 3 个带文本的 div (1, 2, 3)。

当用户将鼠标悬停在每个 div 上时,它应该改变图像。

我有一个 1s 的缓动过渡以使其平滑。

BUG

如果您将鼠标悬停在不同 div 上的速度过快,则过渡会不稳定或无法加载。我正在寻找一种解决方案,用户可以快速浏览 div,并且图像将缓慢过渡到最新的 div。提前谢谢你。

CODEPEN 演示

Codepen

现场演示:

img1 = 'url(https://images.unsplash.com/photo-1533273859801-d731381dfe2d)';
img2 = 'url(https://images.unsplash.com/photo-1534939444268-6a9ff2733c32)';
img3 = 'url(https://images.unsplash.com/photo-1534841515798-3d43f5434123)';

$('.p1').hover(function(){
	$('.bg').css({'background-image': img1});
});

$('.p2').hover(function(){
	$('.bg').css({'background-image': img2});
});

$('.p3').hover(function(){
	$('.bg').css({'background-image': img3});
});
body {
  margin: 0;
  font-family: sans-serif;
}

.bg {
  position: absolute;
  width: 100%;
  height: 100%;
  background: url(https://images.unsplash.com/photo-1533273859801-d731381dfe2d) no-repeat center;
  background-size: cover;
  z-index: -1;
  background-color: #989898;
  background-blend-mode: multiply;
  transition: background-image 1s ease
}

.projects {
  position: absolute;
  margin: auto;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100vw;
  height: 16em;
}

.p {
  font-size: 1.2em;
  position: relative;
  padding: 2rem 0;
  color: #fff;
  opacity: 0.5;
  letter-spacing: 4px;
  text-indent: 4px;
  font-weight: 400;
  transition: opacity 0.5s ease;
  text-align: center;
}

.p:hover {
  opacity: 1;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bg"></div>
<div class="projects">
  <div class="p p1">1</div>
  <div class="p p2">2</div>
  <div class="p p3">3</div>
</div>

【问题讨论】:

  • 这些图片有多大?别介意波涛汹涌的过渡,他们差点把我的电脑冻住了。
  • @ibrahimmahrir 哈哈,它们来自 unsplash,它们是高分辨率的,但使用我的快速 wifi 仍然是个问题。过渡错误是独立的。
  • 在几次悬停/悬停后错误是否仍然存在?
  • 是的,还是有问题
  • @ibrahimmahrir 用较低分辨率的图像更新了 codepen 演示 codepen.io/grysn/pen/jvbBQd?editors=0110 仍然有问题

标签: javascript jquery css css-transitions transition


【解决方案1】:

我建议您使用mousemove 事件和.on() 方法,而不是.hover() 方法。

那个,能够“缓冲”事件......不会错过任何一个。

.hover() 方法与定义mouseentermouseout 事件处理程序相同(第二个是可选的)。

对于mousemove 事件,事件正确触发的机会(从用户的角度来看)更高,因为它像机关枪一样触发。

为什么...因为您必须“缓冲”这些事件以等待当前转换结束。

现在,您将事件处理程序附加到公共类 .p 并设置“鼠标不活动”的 600 毫秒超时。在该延迟之后,背景将更新为与最后一个.p mousemoved 对应的图像。

虽然用户只是像患有帕金森病的人一样移动鼠标,但背景没有任何变化。 在 mousemove 停止时更新和动画。

img1 = 'url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg)';
img2 = 'url(https://www.focusdogtraining.com/wp-content/uploads/2017/10/puppies.jpg)';
img3 = 'url(https://www-tc.pbs.org/wgbh/nova/assets/img/full-size/clever-dog-lab-merl.jpg)';

var movement;
$(".p").on("mousemove",function(e){

  var target = $(e.target);

  clearTimeout(movement);
  movement = setTimeout(function(){
    console.log("User stopped moving... Updating the image.")

    if(target.hasClass("p1")){
      console.log("image #1");
      $('.bg').css({'background-image': img1});
    }
    if(target.hasClass("p2")){
      console.log("image #2");
      $('.bg').css({'background-image': img2});
    }
    if(target.hasClass("p3")){
      console.log("image #3");
      $('.bg').css({'background-image': img3});
    }
  },600);
});

CodePen 上观看工作演示的效果最好,而不是在 SO sn-p 中(遗憾)。

【讨论】:

  • 向我致敬。这工作得很好,但我注意到如果你在 div 中快速移动,它可能会卡在错误的图像上。我一直在尝试使用 .fadeIn() 和 fadeOut() 但到目前为止没有运气。
  • 向大家致敬!我找到了一种更好的缓冲 mousemove 事件的方法,现在应该很完美了。看看 CodePen。
【解决方案2】:

好的。使用 CSS 是不可能的,所以这里有一个使用 jQuery 的方法。

为了实现过渡,我们必须使用两个 div,一个在背景中,一个在前面,它们会淡化给我们一种过渡的错觉。 .bg div 应该包含这两个 div:

<div class="bg">
  <div class="back"></div>
  <div class="front"></div>
</div>

css 应更改为:

.bg {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -1;
  background-color: #989898;
  background-blend-mode: multiply;
  transition: background-image 1s ease
}

.bg > * {
  background: url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg) no-repeat center;
  background-size: cover;
  position: absolute;
  width: 100%;
  height: 100%;
}

这只是删除任何 css 转换并使内部 div 重叠并与其父级 .bg 一样大。

现在是 js 部分 - 实际转换发生的地方。当鼠标进入.p 区域时,我们只需调用带有相应图像的函数changeTo。该函数将当前图像从前到后,将新图像设置为前图像。这样做会比 css 过渡更不稳定,因为不透明度不匹配。使正面图像成为背面图像应该伴随着正面不透明度的反转。这是通过获取不透明度并从1 中减去它来实现的。在我们这样做之后,我们只是将前面的图像不透明度从现在的任何值设置为1。此动画的速度应该与不透明度有关:

var $back = $(".bg .back"),
  $front = $(".bg .front");

function changeTo(img) {
  $front.stop();                                                            // stop any animation that may be in progress
  var op = $front.css("opacity");                                           // get the opacity value (stoping the animation will let the opacity hanging between 0 and 1 inclusive, so we get that value to transition from it)
  $back.css("background-image", $front.css("background-image"));            // make the front image the back one
  $front.css({
    opacity: 1 - op,                                                        // because we made the front image the back one we need to invert the front image's opacity to give the illusion that the back image (which is now the front one) is shown at the original opacity. That's how math works!
    "background-image": img                                                 // and of course make the front image our desired one
  });
  $front.animate({                                                          // animate the front image's
    opacity: 1                                                              // ... opacity from whatever value it is to 1
  }, 500 * op, "linear");                                                   // in a period of 0.5s accouunting for the opacity delta, in other words animating from opacity 0.5 to 1 will take only half the time as animating from 0 to 1. That also how math works! :P
}

$('.p1').on("mouseenter", function() {                                       // when mouse enters .p1
  changeTo(img1);                                                            // change to img1
});

$('.p2').o...

工作示例:

var img1 = 'url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg)';
var img2 = 'url(https://www.focusdogtraining.com/wp-content/uploads/2017/10/puppies.jpg)';
var img3 = 'url(https://www-tc.pbs.org/wgbh/nova/assets/img/full-size/clever-dog-lab-merl.jpg)';

var $back = $(".bg .back"),
  $front = $(".bg .front");

function changeTo(img) {
  $front.stop();
  var op = $front.css("opacity");
  $back.css("background-image", $front.css("background-image"));
  $front.css({
    opacity: 1 - op,
    "background-image": img
  });
  $front.animate({
    opacity: 1
  }, 500, "linear");
}

$('.p1').on("mouseenter", function() {
  changeTo(img1);
});

$('.p2').on("mouseenter", function() {
  changeTo(img2);
});

$('.p3').on("mouseenter", function() {
  changeTo(img3);
});
.bg {
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: -1;
  background-color: #989898;
  background-blend-mode: multiply;
  transition: background-image 1s ease
}

.bg > * {
  background: url(http://ejournalz.com/wp-content/uploads/2017/06/Dog-Care.jpg) no-repeat center;
  background-size: cover;
  position: absolute;
  width: 100%;
  height: 100%;
}

.projects {
  position: absolute;
  margin: auto;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100vw;
  height: 16em;
}

.p {
  font-size: 1.2em;
  position: relative;
  padding: 2rem 0;
  color: #fff;
  opacity: 0.5;
  letter-spacing: 4px;
  text-indent: 4px;
  font-weight: 400;
  transition: opacity 0.5s ease;
  text-align: center;
}

.p:hover {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bg">
  <div class="back"></div>
  <div class="front"></div>
</div>
<div class="projects">
  <div class="p p1">1</div>
  <div class="p p2">2</div>
  <div class="p p3">3</div>
</div>

【讨论】:

    猜你喜欢
    • 2015-12-11
    • 2018-12-05
    • 1970-01-01
    • 2016-02-13
    • 2014-08-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多