方向感知悬停效果

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

这是一个特殊的网页设计技巧,它总是能吸引人们的眼球!我不知道是谁最先想到这个想法,以及所有这些事情的历史,但我确实知道,这些年来我见过许多此类效果的实现。我想在这里总结一些。

Noel Delagado

查看 CodePen 上 Noel Delgado (@noeldelgado) 编写的笔 方向感知 3D 悬停效果(概念)

此处的检测通过跟踪 mouseovermouseout 事件上的鼠标位置并计算跨越的哪一侧来完成。这是一小段巧妙的 JavaScript 代码,其核心是找出该方向。

var getDirection = function (ev, obj) {
    var w = obj.offsetWidth,
        h = obj.offsetHeight,
        x = (ev.pageX - obj.offsetLeft - (w / 2) * (w > h ? (h / w) : 1)),
        y = (ev.pageY - obj.offsetTop - (h / 2) * (h > w ? (w / h) : 1)),
        d = Math.round( Math.atan2(y, x) / 1.57079633 + 5 ) % 4;
  
    return d;
};

然后根据该方向应用类名以触发方向性 CSS 动画。

Fabrice Weinberg

查看 CodePen 上 Fabrice Weinberg (@FWeinb) 编写的笔 方向感知悬停纯 CSS

Fabrice 这里只使用纯 CSS。他们没有检测传出的方向,但他们确实通过四个隐藏的可悬停框检测传入的方向,每个框都旋转以覆盖一个三角形。像这样

Codrops

演示

在 Mary Lou 于 2012 年在 Codrops 上发表的一篇文章中,使用 CSS3 和 jQuery 实现方向感知悬停效果,检测也是在 JavaScript 中完成的。这是插件的这部分代码

_getDir: function (coordinates) {
    // the width and height of the current div
    var w = this.$el.width(),
        h = this.$el.height(),
        // calculate the x and y to get an angle to the center of the div from that x and y.
        // gets the x value relative to the center of the DIV and "normalize" it
        x = (coordinates.x - this.$el.offset().left - (w / 2)) * (w > h ? (h / w) : 1),
        y = (coordinates.y - this.$el.offset().top - (h / 2)) * (h > w ? (w / h) : 1),
        // the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);
        // first calculate the angle of the point,
        // add 180 deg to get rid of the negative values
        // divide by 90 to get the quadrant
        // add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
        direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
    return direction;
},

不过,从技术上讲,CSS 负责执行动画,因为根据需要将内联样式应用于元素。

John Stewart

查看 CodePen 上 John Stewart (@johnstew) 编写的笔 方向感知悬停效果

John 依靠 Greensock 来完成此处的所有检测和动画工作。与所有示例一样,它也有自己的几何数学来计算元素悬停的方向。

// Detect Closest Edge
function closestEdge(x,y,w,h) {
    var topEdgeDist = distMetric(x,y,w/2,0);
    var bottomEdgeDist = distMetric(x,y,w/2,h);
    var leftEdgeDist = distMetric(x,y,0,h/2);
    var rightEdgeDist = distMetric(x,y,w,h/2);
    var min = Math.min(topEdgeDist,bottomEdgeDist,leftEdgeDist,rightEdgeDist);
    switch (min) {
        case leftEdgeDist:
            return "left";
        case rightEdgeDist:
            return "right";
        case topEdgeDist:
            return "top";
        case bottomEdgeDist:
            return "bottom";
    }
}

// Distance Formula
function distMetric(x,y,x2,y2) {
    var xDiff = x - x2;
    var yDiff = y - y2;
    return (xDiff * xDiff) + (yDiff * yDiff);
}

Gabrielle Wee

查看 CodePen 上 Gabrielle Wee ✨ (@gabriellewee) 编写的笔 纯 CSS 方向感知立方体链接

Gabrielle 完全通过 CSS 完成了这项工作,方法是定位四个可悬停的子元素,这些元素根据悬停的哪个元素来触发兄弟元素(立方体)上的动画。这里有一些棘手的东西涉及到 clip-path 和转换,我承认我并不完全理解。可悬停区域似乎不像您预期的那样是三角形,而是覆盖一半区域的矩形。看起来它们会无效地重叠,但它们似乎没有。我认为这可能是因为它们稍微悬挂在边缘上,从而形成了一个悬停区域,允许每个边缘具有完整的边缘覆盖范围。

Elmer Balbin

查看 CodePen 上 Elmer Balbin (@elmzarnsi) 编写的笔 使用 clip-path 纯 CSS 实现方向感知图块

Elmer 这里也使用了 clip-path,但四个可悬停元素被剪裁成三角形。您可以看到它们中的每一个都在 50% 50%(正方形的中心)处有一个点,并且还有另外两个角点。

clip-path: polygon(0 0, 100% 0, 50% 50%)
clip-path: polygon(100% 0, 100% 100%, 50% 50%);
clip-path: polygon(0 100%, 50% 50%, 100% 100%);
clip-path: polygon(0 0, 50% 50%, 0 100%);

Nigel O Toole

演示

原始 JavaScript 为 Nigel 的此处演示提供动力,该演示已全部现代化,可以使用 npm 和模块以及所有这些内容。不过,计算方式很熟悉。

const _getDirection = function (e, item) {
  // Width and height of current item
  let w = item.offsetWidth;
  let h = item.offsetHeight;
  let position = _getPosition(item);

  // Calculate the x/y value of the pointer entering/exiting, relative to the center of the item.
  let x = (e.pageX - position.x - (w / 2) * (w > h ? (h / w) : 1));
  let y = (e.pageY - position.y - (h / 2) * (h > w ? (w / h) : 1));

  // Calculate the angle the pointer entered/exited and convert to clockwise format (top/right/bottom/left = 0/1/2/3).  See https://stackoverflow.com/a/3647634 for a full explanation.
  let d = Math.round(Math.atan2(y, x) / 1.57079633 + 5) % 4;

  // console.table([x, y, w, h, e.pageX, e.pageY, item.offsetLeft, item.offsetTop, position.x, position.y]);

  return d;
};

JavaScript 最终应用类,这些类根据一些 花哨的 Sass 生成的动画在 CSS 中进行动画处理。

Giana

一个纯 CSS 实现,可以很好地处理传出的方向!

查看 CodePen 上 Giana (@giana) 编写的笔 纯 CSS 方向感知悬停


您是否在其他地方见过?您是否在构建的某些内容中使用过此功能?