简体   繁体   English

悬停时的多图像转换

[英]Multiple Image Transition on Hover

CODE

I have 3 divs with text (1, 2, 3). 我有3个带文字的div(1,2,3)。

When the user hovers over each div, it should change the image. 当用户将鼠标悬停在每个div上时,它应该更改图像。

I have a 1s ease transition to make it smooth. 我有一个简单的过渡,使其顺利。

BUG BUG

If you hover over different divs too quickly, the transition is choppy or doesn't load. 如果您将鼠标悬停在不同的div上太快,则转换不稳定或无法加载。 I'm looking for a solution where the user can quickly move through the divs and the image will transition slowly to whichever is the newest div. 我正在寻找一种解决方案,用户可以快速浏览div,图像将慢慢转换到最新的div。 Thank you in advance. 先感谢您。

CODEPEN DEMO CODEPEN DEMO

Codepen Codepen

LIVE DEMO: 现场演示:

 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> 

I suggest you to use the mousemove event and the .on() method instead of the .hover() method. 我建议你使用mousemove事件和.on()方法而不是.hover()方法。

That, to be able to "buffer" events... Without missing one. 那,能够“缓冲”事件......没有遗漏一个。

.hover() method is the same as defining a mouseenter and mouseout event handler (the second being optionnal). .hover()方法是相同的限定mouseentermouseout事件处理程序(第二个是optionnal)。

With the mousemove event, the chances for the event to fire correctly (from a user point of view) are higher since it fires like a machinegun. 使用mousemove事件,事件正确触发的可能性(从用户的角度来看)更高,因为它像机枪一样发射。

Why... Because you will have to "buffer" those events to wait for the current transition to end. 为什么...因为您必须“缓冲”这些事件以等待当前转换结束。

Now , you will attach the event handler to the common class .p and set a timeout of 600ms of "mouse inactivity". 现在 ,您将事件处理程序附加到公共类.p并设置600ms的“鼠标不活动”超时。 After that delay, the background wil be updated with the image corresponding with the last .p mousemoved. 在那个延迟之后,将使用与最后一个.p mousemoved对应的图像更新背景。

While the user just move the mouse like someone with parkinson's desease, nothing happens about the background. 虽然用户只是像帕金森病患者一样移动鼠标,但背景没有任何反应。 It is updated and animated only on mousemove stop. 它被更新, 在鼠标移动停止动画。

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);
});

A working demo is best viewed on CodePen than in a SO snippet (sadly). 一个工作演示最好在CodePen上观看, 不是在SO片段中观看(遗憾的是)。

Ok. 好。 This is impossible using CSS, so here is a how to do it using jQuery. 使用CSS是不可能的,所以这里有一个如何使用jQuery。

To acheive the transition, we'll have to use two divs, one in the background and one in the front that will fade in giving us the illusion of transition. 为了实现过渡,我们将不得不使用两个div,一个在背景中,一个在前面,将淡化给我们过渡的幻觉。 The .bg div should contain those two divs: .bg div应包含这两个div:

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

The css should change to: 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%;
}

Which just removes any css transitions and make the inner divs overlap and as big as their parent .bg . 这只是删除任何css过渡并使内部div重叠并与其父.bg一样大。

Now for the js part - where the actual transition takes place. 现在是js部分 - 实际过渡发生的地方。 When the mouse enters a .p area, we just call the function changeTo with the corresponding image. 当鼠标进入.p区域时,我们只需使用相应的图像调用函数changeTo The function takes the current image from the front to the back, sets the new image as the front image. 该功能从前到后获取当前图像,将新图像设置为前图像。 Doing that will be choppier than the css transition because the opacity doesn't match. 这样做会比css过渡更加笨重,因为不透明度不匹配。 Making the front image the back one should be accompaigned with an invertion of the opacity of the front. 使前面的图像成为后面的图像应该与前面的不透明度的倒角相伴。 That is achieved by just getting the opacity and substracting it from 1 . 这是通过获得不透明度并从1减去它来实现的。 After we do that, we just animate the front image opacity from whatever value it is now to 1 . 在我们这样做之后,我们只是将前图像不透明度从现在的任何值设置为1 The speed of this animation should be relative to what the opacity is: 此动画的速度应该与不透明度相关:

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...

Working example: 工作范例:

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM