【问题标题】:jQuery direction-aware hover with CSS3 transition带有 CSS3 过渡的 jQuery 方向感知悬停
【发布时间】:2016-04-26 07:16:50
【问题描述】:

我正在努力让方向感知悬停和 css 过渡正常工作。基本上,我正在尝试使用具有正面和背面的元素网格,并且在悬停时有一个 CSS 过渡来翻转该元素以显示背面。

过渡示例(无方向感知):fiddle

如您所见,无论您的鼠标以哪种方式进入元素,它总是会向上翻转。我希望它翻转鼠标进入/退出的任何方式。

例子:

这是我对方向感知的尝试:fiddle

我正在使用 jQuery 添加与鼠标输入/输出方向相关的类。

.hover-in-top {}
.hover-in-right {}
.hover-in-bottom {}
.hover-in-left {}

.hover-out-top {}
.hover-out-right {}
.hover-out-bottom {}
.hover-out-left {}

正如您从方向感知示例中看到的那样,它有点工作,但有一些我无法理解的重大故障。 (我一直在想这件事,我的大脑刚刚崩溃。)

无论如何,我希望这是有道理的。谢谢。

【问题讨论】:

  • 我一眼就能看出几个问题。 1:如果你垂直悬停,然后水平悬停,会发生什么?如果您垂直翻转,然后水平翻转,则内容将上下颠倒。 2:你在.box 上收听悬停事件,它也被转换了。换句话说,悬停区域会随着变换而变化。也许您应该为悬停事件使用永久容器。
  • @CedricReichenbach 您提出了 2 个非常好的观点。尤其是你的第一个。我想我将不得不重新考虑用户体验。谢谢。

标签: javascript jquery css css-transitions


【解决方案1】:

我对你的问题有部分解决方案。

但我需要将一些过渡更改为动画

$('.box-container .box').each(function() {
    $(this).on('mouseenter mouseleave', function(e) {
        var $this = $(this),
            width = $this.width(),
            height = $this.height();

        var x = (e.pageX - $this.offset().left - (width / 2)) * (width > height ? (height / width) : 1),
            y = (e.pageY - $this.offset().top - (height / 2)) * (height > width ? (width / height) : 1);

        // top = 0, right = 1, bottom = 2, left = 3
        var dir_num = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4,
            directions = ['top', 'right', 'bottom', 'left'];

        // If mouse enter
        if (e.type === 'mouseenter') {
            // Remove all hover out classes
            $this.removeClass(function(index, css) {
                return (css.match(/(^|\s)hover-out-\S+/g) || []).join(' ');
            });

            // Add in direction class
            $this.addClass('hover-in-' + directions[dir_num]);
        }


        // If mouse leave
        if (e.type === 'mouseleave') {
            // Remove all hover in classes
            $this.removeClass(function(index, css) {
                return (css.match(/(^|\s)hover-in-\S+/g) || []).join(' ');
            });

            // Add out direction class
            $this.addClass('hover-out-' + directions[dir_num]);
        }
    });
});
* {
    box-sizing: border-box;
}

.box-container {
    padding: 20px;
    width: 600px;
}
.box-container:after {
    content: '';
    display: block;
    clear: both;
}
.box-container .box {
    float: left;
    width: 50%;
    height: 200px;
    position: relative;
    perspective: 600px;
    border: 1px solid transparent;
}
.box-container .box .front, .box-container .box .back {
    float: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    backface-visibility: hidden;
    transition: all 1s ease-in-out;
    color: white;
    font-size: 60px;
}
.box-container .box .front {
    background: blue;
    transform: rotateX(0) rotateY(0);
    z-index: 900;
}
.box-container .box .back {
    background: red;
    z-index: 800;
}
.box-container .box:hover .front {
    z-index: 900;
}
.box-container .box:hover .back {
    z-index: 1000;
    transform: rotateX(180) rotateY(0);
}

.box-container .box.hover-in-top .front,
.box-container .box.hover-out-bottom .back {
    transform: rotateX(-179deg) rotateY(0);
}
.box-container .box.hover-in-top .back,
.box-container .box.hover-out-bottom .front {
    animation: Xminus 1s ease-in-out;
}
@keyframes Xminus {
    from {transform: rotateX(179deg) rotateY(0);}
    to   {transform: rotateX(  0deg) rotateY(0);}
}

.box-container .box.hover-in-bottom .front,
.box-container .box.hover-out-top .back {
    transform: rotateX(179deg);
}
.box-container .box.hover-in-bottom .back,
.box-container .box.hover-out-top .front {
    animation: Xplus 1s ease-in-out;
}
@keyframes Xplus {
    from {transform: rotateX(-179deg) rotateY(0);}
    to   {transform: rotateX(   0deg) rotateY(0);}
}

.box-container .box.hover-in-right .front,
.box-container .box.hover-out-left .back {
    transform: rotateY(-179deg);
}
.box-container .box.hover-in-right .back,
.box-container .box.hover-out-left .front {
    animation: Yminus 1s ease-in-out;
}
@keyframes Yminus {
    from {transform: rotateX(0deg) rotateY(179deg);}
    to   {transform: rotateX(0deg) rotateY(  0deg);}
}

.box-container .box.hover-in-left .front,
.box-container .box.hover-out-right .back {
    transform: rotateY(179deg);
}

.box-container .box.hover-in-left .back,
.box-container .box.hover-out-right .front {
    animation: Yplus 1s ease-in-out;
}
@keyframes Yplus {
    from {transform: rotateX(0deg) rotateY(-179deg);}
    to   {transform: rotateX(0deg) rotateY(  0deg);}
}
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box-container">
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
    <div class="box">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
    </div>
</div>

如果你在动画结束之前离开 div,动画就会中断

但是如果移动缓慢,并且一直停留在 div 上直到动画结束,这样就可以了。

希望有人能找到更好的解决方案

【讨论】:

    【解决方案2】:

    我认为解决问题的最佳方法是不使用 CSS 过渡。

    您可以使用 jQuery 的 animate 轻松实现它,利用 jQuery 动画队列保持所有动画同步。

    我修改了您的示例以在 JavaScript 中为过渡设置动画。

    Code example

    【讨论】:

      猜你喜欢
      • 2012-08-28
      • 2015-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-08
      • 1970-01-01
      • 2012-03-12
      • 2021-01-24
      相关资源
      最近更新 更多