如何在鼠标悬停时保持CSS三角形的正确边界?

12
有没有可能修复http://jsfiddle.net/2AXhR/上的悬停效果,使正确的三角形在悬停时被激活,而不是其相邻的三角形?有时会激活错误的三角形,因为每个三角形元素的边界区域实际上不是一个三角形,而是一个矩形,所以即使光标可能出现在一个三角形的顶部,它实际上也可能出现在另一个重叠且具有更高z-index的三角形的顶部。

黄色覆盖层显示了右上角三角形的边界。它与下面的相邻三角形重叠,这意味着当光标处于两者共享的小区域内时,行为不一致。

  <style type="text/css">
  .t {
     position:relative;
     top:55px;
     left:5px;
  }
  .t div {
     position:absolute;
     width: 0px;
     height: 0px;
     border-style: solid;
     border-width: 0 100px 173.2px 100px;
     border-color: transparent transparent #0079c5 transparent;
     transition:all 1s;
     -webkit-transition:all 1s;
     -moz-transition:all 1s;
     cursor:pointer;
     transform-origin:200px 173px;
     -webkit-transform-origin:200px 173px;
     -moz-transform-origin:200px 173px;
     z-index:10;
  }
  .t div:hover {
      z-index:20;
      border-color: transparent transparent #009cff transparent;
  }
  .t div:nth-child(1) {
     transform:rotate(30deg);
     -webkit-transform:rotate(30deg);
     -moz-transform:rotate(30deg);
  }
  .t div:nth-child(1):hover {
     transform:rotate(30deg) translate(-15%, -10%);
     -webkit-transform:rotate(30deg) translate(-15%, -10%);
     -moz-transform:rotate(30deg) translate(-15%, -10%);
  }
  .t div:nth-child(2) {
     transform:rotate(90deg);
     -webkit-transform:rotate(90deg);
     -moz-transform:rotate(90deg);
  }
  .t div:nth-child(2):hover {
     transform:rotate(90deg) translate(-15%, -10%);
     -webkit-transform:rotate(90deg) translate(-15%, -10%);
     -moz-transform:rotate(90deg) translate(-15%, -10%);
  }
  .t div:nth-child(3) {
     transform:rotate(150deg);
     -webkit-transform:rotate(150deg);
     -moz-transform:rotate(150deg);
  }
  .t div:nth-child(3):hover {
     transform:rotate(150deg) translate(-15%, -10%);
     -webkit-transform:rotate(150deg) translate(-15%, -10%);
     -moz-transform:rotate(150deg) translate(-15%, -10%);
  }
  .t div:nth-child(4) {
     transform:rotate(210deg);
     -webkit-transform:rotate(210deg);
     -moz-transform:rotate(210deg);
  }
  .t div:nth-child(4):hover {
     transform:rotate(210deg) translate(-15%, -10%);
     -webkit-transform:rotate(210deg) translate(-15%, -10%);
     -moz-transform:rotate(210deg) translate(-15%, -10%);
  }
  .t div:nth-child(5) {
     transform:rotate(270deg);
     -webkit-transform:rotate(270deg);
     -moz-transform:rotate(270deg);
  }
  .t div:nth-child(5):hover {
     transform:rotate(270deg) translate(-15%, -10%);
     -webkit-transform:rotate(270deg) translate(-15%, -10%);
     -moz-transform:rotate(270deg) translate(-15%, -10%);
  }
  .t div:nth-child(6) {
     transform:rotate(330deg);
     -webkit-transform:rotate(330deg);
     -moz-transform:rotate(330deg);
  }
  </style>

  <div class="t">
     <div></div>
     <div></div>
     <div></div>
     <div></div>
     <div></div>
     <div></div>
  </div>

1
在Firefox 27中运行非常好,无法重现您所描述的情况。您在哪里遇到这些问题,或者有什么方法可以重现您试图解决的问题?顺便说一句,迄今为止做得很好。 :) - try-catch-finally
你需要支持IE 8浏览器吗? - web-tiki
1
我刚刚编辑了我的帖子,加入了一张图片和一个新的JSFiddle,在那里你可以修改六边形的属性。试着把你的光标放在右上角三角形的正下方,你会发现即使光标超出了其边界,它仍然激活它而不是下面相邻的三角形。我不需要支持IE8。 - Dane Iracleous
你可以在每个三角形中创建一个三角形,内部三角形的尺寸恰好是矩形剩余部分的三角形形状的尺寸,因此悬停或鼠标悬停只会在右侧三角形上工作,而不是整个矩形。 - MujtabaFR
@Web-tiki,你看过代码了吗?IE8?真的吗? - Yaron U.
显示剩余2条评论
3个回答

12

----- 版本2,更加简洁和优化(修复IE和Firefox的问题) -----

修正的问题:

  1. IE忽略了overflow:hidden;属性,导致悬停事件在可见三角形之外触发。
  2. 出现了一些在Firefox中三角形上出现的线条。
  3. 如果光标位于三角形之间,则会返回默认状态。

描述:

这种方法使用skewX()来创建三角形。你不需要使用"border trick"来创建它们,也不需要使用overflow属性。使用这种技术,没有任何重叠的元素,因此悬停事件不能同时触发两个元素。

第二个

隐藏了倾斜元素的一半,以创建三角形,并使用+ CSS选择器在悬停时与其一起平移。


----- 演示V2 ----- 开发工具显示三角形边界的快照




标记:

<div class="t">
    <div class="wrap">
        <div class="triangle"></div>
        <div class="mask"></div>
    </div>
   <div class="wrap">
        <div class="triangle"></div>
        <div class="mask"></div>
    </div>
    <div class="wrap">
        <div class="triangle"></div>
        <div class="mask"></div>
    </div>
    <div class="wrap">
        <div class="triangle"></div>
        <div class="mask"></div>
    </div>
    <div class="wrap">
        <div class="triangle"></div>
        <div class="mask"></div>
    </div>
    <div class="wrap">
        <div class="triangle"></div>
        <div class="mask"></div>
    </div>
</div>

CSS :

.t div{
    position:absolute;
    top:0; left:0;

    transform-origin:0 0;
    -ms-transform-origin:0 0;
    -webkit-transform-origin:0 0;

    transition:all 1s;
    -webkit-transition:all 1s;
    -moz-transition:all 1s;
}

.t .wrap{
    top:50%; left:50%;

    -ms-transform: skewX(30deg);
    -webkit-transform: skewX(30deg);
    transform: skewX(30deg);
}

.t .wrap .triangle {
    position:relative;
    width: 200px;
    height: 173px;
    background-color: #0079c5;
    cursor:pointer;
    z-index:1;
}
.t .wrap .mask{
    width:100%;
    height:115.5%;
    background-color: #fff;
    left:100%;
    z-index:2;

    -ms-transform: skewX(-30deg) rotate(30deg);
    -webkit-transform: skewX(-30deg) rotate(30deg);
    transform: skewX(-30deg) rotate(30deg);
} 

.t .wrap .triangle:hover{
    background-color: #009cff;

    transform:  translate(10%, 10%);
    -webkit-transform: translate(10%, 10%);
    -moz-transform: translate(10%, 10%);
}

.t .triangle:hover + .mask{
    -ms-transform: skewX(-30deg) rotate(30deg) translate(17.5%, 0);
    -webkit-transform: skewX(-30deg) rotate(30deg) translate(17.5%, 0);
    transform: skewX(-30deg) rotate(30deg) translate(17.5%, 0);
}

.t > div:nth-child(2){
    -ms-transform: rotate(60deg) skewX(30deg);
    -webkit-transform: rotate(60deg) skewX(30deg);
    transform: rotate(60deg) skewX(30deg);
}
.t > div:nth-child(3){
    -ms-transform: rotate(120deg) skewX(30deg);
    -webkit-transform: rotate(120deg) skewX(30deg);
    transform: rotate(120deg) skewX(30deg);
}

.t > div:nth-child(4){
    -ms-transform: rotate(-60deg) skewX(30deg);
    -webkit-transform: rotate(-60deg) skewX(30deg);
    transform: rotate(-60deg) skewX(30deg);
}
.t > div:nth-child(5){
    -ms-transform: rotate(-120deg) skewX(30deg);
    -webkit-transform: rotate(-120deg) skewX(30deg);
    transform: rotate(-120deg) skewX(30deg);
}
.t > div:nth-child(6){
    -ms-transform: rotate(-180deg) skewX(30deg);
    -webkit-transform: rotate(-180deg) skewX(30deg);
    transform: rotate(-180deg) skewX(30deg);
}




版本 1(原版):示范版 V1 的 fiddle


1
不错的方法 - 我喜欢每个三角形外边缘的边界也被保留的方式。我想,既然你正在扭曲整个元素,那么为什么我们还需要使用创建三角形的边框方法呢?为什么不只设置宽度、高度和背景颜色呢?我从你的 fiddle 中分叉出来尝试了一下,但即使在扭曲的父 div 上设置了 overflow:hidden,子元素仍然显示为矩形。看看这个:http://jsfiddle.net/zVAa2/ - Dane Iracleous
1
啊,好的。我们所有实现中我不喜欢的一件事是三角形之间的空白太多了。看起来有些过度了。我想知道是否有办法改进抗锯齿或其他什么方法。Josh Crozier能够消除所有空白,但他不能使用动画。 - Dane Iracleous
@DaneIracleous 看看这个,我加了一些抗锯齿效果,使用-webkit-backface-visibility: hidden;来适配Chrome,并减少了空格:http://jsfiddle.net/webtiki/bZxn9/。但是在上下三角形旁边仍然有一个小问题,我会继续寻找解决方法。 - web-tiki
1
我认为你已经完美地完成了这个项目。我真的很喜欢v2拥有如此精确的边缘。当光标悬停在三角形之间的空白处时,如果将其放置在其中一个上,光标会回到默认状态而不是指针。这比我的实现有了很大的改进。 - Dane Iracleous
@DaneIracleous 这是真的,我没有意识到! - web-tiki
显示剩余4条评论

4

这里有一种完全不同的方法,它完全避免了边界问题。

值得注意的是,当涉及到实现您所设置的悬停效果时,这种方法相对有限。我目前正在寻找替代方案。

示例在此 - 在Firefox / Chrome中有效,在IE11中失败。

HTML

<div class="t">
    <div class="clip">
        <div class="triangle"></div>
    </div>
    <div class="clip">
        <div class="triangle"></div>
    </div>
    <div class="clip">
        <div class="triangle"></div>
    </div>
    <div class="clip">
        <div class="triangle"></div>
    </div>
    <div class="clip">
        <div class="triangle"></div>
    </div>
    <div class="clip">
        <div class="triangle"></div>
    </div>
</div>

CSS

.t {
    width:500px;
    height:500px;
    position:relative;
}
.t > .clip {
    overflow: hidden;
    position: absolute;
    width: 50%;
    height: 50%;
    -webkit-transform-origin: 100% 100%;
}
.t > .clip:first-child {
    -webkit-transform: rotate(60deg) skewY(30deg);
}
.t > .clip:nth-child(2) {
    -webkit-transform: rotate(120deg) skewY(30deg);
}
.t > .clip:nth-child(3) {
    -webkit-transform: rotate(180deg) skewY(30deg);
}
.t > .clip:nth-child(4) {
    -webkit-transform: rotate(240deg) skewY(30deg);
}
.t > .clip:nth-child(5) {
    -webkit-transform: rotate(300deg) skewY(30deg);
}
.t > .clip:nth-child(6) {
    -webkit-transform: rotate(360deg) skewY(30deg);
}
.triangle {
    width: 200%;
    height: 200%;
    -webkit-transform: skewY(-42deg) skewX(-20deg) rotate(-15.5deg);
    background:#0079c5;
}
.triangle:hover {
    background:#009cff;
}

这是一个有趣的方法,我没有考虑过。我尝试编辑你的fiddle,使用悬停动画,其中三角形向外移动,但三角形本身占据了整个屏幕的部分,因此在空白处应该出现的空白边距不存在。它只是更多的三角形。 - Dane Iracleous

3

我实际上自己解决了这个问题。使用JavaScript,我为每个三角形设置了一个悬停事件:在悬停时,将其自身的z-index设置为20,下一个三角形的z-index设置为21,所有其他三角形的z-index设置为19。

代码如下:

  self.e.find(".t div").hover(
  function() {
     $(this).css({
        'z-index': 20,
        'border-color': "transparent transparent "+self.params['colorSelected']+" transparent"
     });
     if($(this).next().length) {
        $(this).next().css("z-index", 21);
     } else {
        self.e.find(".t div").first().css("z-index", 21);
     }
  }, 
  function() {
     self.e.find(".t div").css({
        'z-index': 19,
        'border-color': "transparent transparent "+self.params['color']+" transparent"
     });
  });

它能够起作用的原因是所有的三角形都按顺序排列,从左上角开始顺时针旋转。每个三角形错误地重叠其下一个兄弟元素,因此通过将下一个兄弟元素在z平面上向前移动,可以使得三角形正确定义。
比较这两个JSFiddles,您将看到悬停行为的区别:
尚未解决:http://jsfiddle.net/2AXhR/ 已解决:http://jsfiddle.net/2AXhR/1/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接