javascript - 在鼠标悬停时反转文本颜色

标签 javascript html css

我想在用自定义 -black- 光标悬停时反转黑色文本。 这个 GIF 演示了效果:

无法全神贯注地使用 CSS 和 JS 来完成这项工作。我猜是混合混合模式、剪贴蒙版、伪元素和滤镜的一些组合。

以下代码使光标变为白色,但不允许将黑色文本变为白色。听起来很抽象?这是一个 demo .

// All creds go to https://murmure.me 👀

const cursor = $(".cursor"),
      body = $("body"),
      slider = $(".slider"),
      nav = $(".nav"),
      fail = $(".fail"),
      invert = $(".invert"),
      nav_open_menu = $(".navopen"),
      wwidth = $(window).width(),
      wheight = $(window).height(),
             
cursorMove = function() {
  var e, n;
  return (
    body.addClass("cursor-on"),
    cursor.css({
      transform: "matrix(1, 0, 0, 1, " + wwidth / 2 + ", " + wheight / 2 + ")"
    }),
    (e = wheight / 2),
    (n = 0.65 * wwidth / 2),
    n > e ? e : n,
    $(window).on("mousemove", function(e) {
      var n, t;
      if (
        ((window.x = e.clientX),
        (window.y = e.clientY),
        cursor.css({
          transform: "matrix(1, 0, 0, 1, " + x + ", " + y + ")"
        }),
        !nav.hasClass("overlay-visible"))
      )
        return (
          (n = Math.floor((x - 60) / 5)),
          (t = Math.floor((y - 60) / 5)),
          n < 20 && t < 20
            ? nav_open_menu.addClass("magnetize").css({
                transform: "scale(1.3) translate3d(" + n + "px, " + t + "px, 0)"
              })
            : nav_open_menu.removeClass("magnetize").attr("style", "")
        );
    })
  );
};
cursorBind = function() {
    var e, n, t;
    if (
      ((n = cursor.find("span")).removeClass("link external new"),
      (e = $(".focus")),
      (t = $(".slack")),
      $(window).on({
        mouseenter: function() {
          return n.removeClass("off");
        },
        mouseleave: function() {
          return n.addClass("off");
        }
      }),
      $("a, button, .cursor-link, .sort-listing th").on({
        mouseenter: function() {
          var e;
          return (
            (e = $(this).hasClass("external") ? "link external" : "link"),
            n.addClass(e)
          );
        },
        mouseleave: function() {
          return n.removeClass("link external");
        }
      }),
      $("h1").on({
        mouseenter: function() {
          var e;
          return (
            (e = $(this).hasClass("external") ? "invert external" : "invert"),
            n.addClass(e)
          );
        },
        mouseleave: function() {
          return n.removeClass("invert external");
        }
      }),
      e.length &&
        e.find("a").on({
          mouseenter: function() {
            return n.addClass("new");
          },
          mouseleave: function() {
            return n.removeClass("new");
          }
        }),
      slider.length &&
        slider.on({
          mouseenter: function() {
            var e;
            return (
              (e = $(this).hasClass("full") ? "click" : "drag"), n.addClass(e)
            );
          },
          mouseleave: function() {
            return n.removeClass("drag click");
          }
        }),
      t.length &&
        t.on({
          mouseenter: function() {
            return n.addClass("light");
          },
          mouseleave: function() {
            return n.removeClass("light");
          }
        }),
      fail.length)
    )
      return fail.on({
        mouseover: function() {
          return n.addClass("relol");
        },
        mouseleave: function() {
          return n.removeClass("relol");
        }
      });
  };

cursorMove();
cursorBind();
body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

h1 {
  font-weight: 500;
  font-size: 9vw;
}
 

*, *:before, *:after {
	 box-sizing: border-box;
}
 body {
	 min-height: 100vh;
	 background-color: #fff;
	 color: #000;
	 text-rendering: optimizelegibility;
	 line-height: 1.5;
	/* System stack font-family mentioned by @wooorm */
	 font-family: Roboto, -apple-system, BlinkMacSystemFont, Helvetica Neue, Segoe UI, Oxygen, Ubuntu, Cantarell, Open Sans, sans-serif;
}
 .cursor-on {
	 cursor: none;
}
 .cursor-on * {
	 cursor: none;
}
 .cursor-on .cursor {
	 position: fixed;
	 z-index: 10;
	 pointer-events: none;
	 top: -1rem;
	 left: -1rem;
}
 .cursor-on .cursor > span {
	 display: block;
	 width: 2rem;
	 height: 2rem;
	 border-radius: 2rem;
	 background: #f8e71c;
	 transition: transform 0.2s cubic-bezier(0.165, 0.84, 0.44, 1);
	 transform: scale(1);
}
 .cursor-on .cursor > span.off {
	 transform: scale(0);
}
 .cursor-on .cursor > span.link {
	 transform: scale(1.5);
	 background-color: #0000ed;
}
 .cursor-on .cursor > span.link.external:after {
	 content: "↗";
	 display: block;
	 white-space: pre;
	 color: #fff;
	 font-weight: 100;
	 font-size: 1rem;
	 text-align: center;
	 width: 100%;
	 line-height: 1;
	 padding-top: 0.6em;
}
 .cursor-on .cursor > span.light {
	 background: #fff;
}
 .cursor-on .cursor > span.drag, .cursor-on .cursor > span.click, .cursor-on .cursor > span.relol, .cursor-on .cursor > span.new {
	 transform: scale(2.5);
}
 .cursor-on .cursor > span.drag:after, .cursor-on .cursor > span.click:after, .cursor-on .cursor > span.relol:after, .cursor-on .cursor > span.new:after {
	 display: block;
	 content: "";
	 white-space: pre;
	 color: #fff;
	 font-size: 5px;
	 text-align: center;
	 width: 100%;
	 line-height: 1;
	 padding-top: calc((2rem / 2) - 2.5px);
	 color: #000;
}
 .cursor-on .cursor > span.drag:after {
	 content: "play";
}
 .cursor-on .cursor > span.click:after {
	 content: "click\A click";
}
 .cursor-on .cursor > span.relol:after {
	 content: "click\A me";
	 padding-top: calc((2rem / 2) - 5px);
}
 .cursor-on .cursor > span.new:after {
	 content: "new\A new";
}
 .cursor-on:active .cursor > span {
	 transform: scale(0.75);
}
 .cursor-on:active .cursor > span.link {
	 transform: scale(1);
}
 .cursor-on:active .cursor > span.drag, .cursor-on:active .cursor > span.click, .cursor-on:active .cursor > span.relol, .cursor-on:active .cursor > span.new {
	 transform: scale(2);
}
 .grid {
	 background-color: #fff;
}
 .grid--column--item {
	 background-color: #000;
}
 .grid--column.sticky .grid--column--item {
	 border-color: #000;
}


.cursor-on .cursor > span {
	 background: black;
}
 .cursor-on .cursor > span.invert {
	 transform: scale(2.5);
	 mix-blend-mode: difference;
	 filter: invert(1) grayscale(1) contrast(2);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 class="invert">Work</h1>


<div class="cursor" >
  <span class="off"></span>
 </div>

mix-blend-mode: difference;
filter: invert(1) grayscale(1) contrast(2);

我设置了一个 playground on Codepen乱来,还没找到解决办法。

如何使用 CSS 和 Javascript 重新创建这种悬停效果?

最佳答案

这是一个使用clip-path 的想法。诀窍是复制文本,使其在彼此之上有两层,文本颜色不同,然后我使用移动鼠标调整的 clip-path 显示最上面的一层。

var h =document.querySelector('h1');
var p= h.getBoundingClientRect();
var c= document.querySelector('.cursor');

document.body.onmousemove = function(e) {
  /*Adjust the cursor position*/
  c.style.left=e.clientX+'px';
  c.style.top=e.clientY+'px';
  /*Adjust the clip-path*/
  h.style.setProperty('--x',(e.clientX-p.top)+'px');
  h.style.setProperty('--y',(e.clientY-p.left)+'px');
}
body {
  cursor:none;
}
h1 {
  color: #000;
  display:inline-block;
  margin:50px;
  text-align: center;
  position:relative;
}
h1:before {
  position:absolute;
  content:attr(data-text);
  color:#fff;
  background:#000;
  clip-path: circle(20px at var(--x,-100%) var(--y,-100%));
}
.cursor {
  position:fixed;
  width:40px;
  height:40px;
  background:#000;
  border-radius:50%;
  top:0;
  left:0;
  transform:translate(-50%,-50%);
  z-index:-2;
}
<h1 data-text="WORK">WORK</h1>

<span class="cursor"></span>

这是另一个使用 radial-gradient 并且不复制可以同时处理多个元素的文本的想法:

document.body.onmousemove = function(e) {
  document.documentElement.style.setProperty('--x',(e.clientX)+'px');
  document.documentElement.style.setProperty('--y',(e.clientY)+'px');
}
body {
  cursor:none;
}

.mask {
  background: 
    radial-gradient(circle 20px 
                    at var(--x,0) var(--y,0), 
                    #fff 99%,black 100%) 
                    fixed;
  background-clip: text;
  -webkit-background-clip: text;
  color:transparent;
  -webkit-text-fill-color: transparent;
}
html::before {
  content:"";
  position:fixed;
  width:40px;
  height:40px;
  background:#000;
  border-radius:50%;
  top:var(--y,0);
  left:var(--x,0);
  transform:translate(-50%,-50%);
  z-index:-2;
}
<h1 class="mask">WORK</h1>
<p class="mask">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis risus sapien. Maecenas dui orci, blandit et commodo eget, egestas quis odio. Donec eu tortor turpis. Aliquam convallis et nisi ut varius. Proin sapien erat, auctor in efficitur vel, efficitur sit amet justo. In pretium iaculis tempus. Vivamus congue</p>

<p class="mask">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis risus sapien. Maecenas dui orci, blandit et commodo eget, egestas quis odio. Donec eu tortor turpis. Aliquam convallis et nisi ut varius. Proin sapien erat, auctor in efficitur vel, efficitur sit amet justo. In pretium iaculis tempus. Vivamus congue</p>

思路相似的相关问题:Stacking circles produces a black bar on border radius

关于javascript - 在鼠标悬停时反转文本颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49793312/

相关文章:

javascript - 如果 DOM 元素获取 "removed",AngularJS Controller 就会被销毁?

javascript - 如何让 Visual Studio 自动包含从 Typescript 编译的 JS 文件?

html - 如何从加载的图像中仅显示 1 个像素并将其平铺

css - 带有动态参数列表的 SASS mixin 仅适用于一个参数

css - 使用样式组件扩展样式不起作用

html - 如何垂直和水平重复图像?

将 JSON 键值对象转换为查询字符串的 JavaScript 函数

javascript - 在一个页面中运行多个 Angular 应用程序

javascript - jQuery UI 可排序项目不起作用

javascript - offsetHeight 获取 div 元素的不正确高度