简体   繁体   English

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

[英]Invert text color on mouse hover

I'd like to invert a black text while hovering it with a custom -black- cursor.我想在使用自定义 -black- 光标悬停时反转黑色文本。 This GIF demonstrates the effect:这个GIF演示了效果:

Couldn't wrap my head around to make this work with CSS & JS.无法用 CSS 和 JS 完成这项工作。 Some combination with mix-blend-modes, clipping masks, pseudo elements and filters I guess.我猜是混合模式、剪切蒙版、伪元素和过滤器的某种组合。

The following code makes the cursor white but doesn't alow the black text to be turned white.以下代码使光标变为白色,但不会使黑色文本变为白色。 Sounds abstract?听起来很抽象? Here's a 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);

I've setup a playground on Codepen to mess around with, but didn't found a solution yet.我已经在 Codepen 上设置了一个操场来捣乱,但还没有找到解决方案。

How could this hover effect be recreated with CSS and Javascript?如何使用 CSS 和 Javascript 重新创建这种悬停效果?

Here is an idea using clip-path .这是一个使用clip-path的想法。 The trick is to duplicate the text to have two layers above each other with different text color then I reveal the top one using the clip-path that I adjust with the move of the mouse.诀窍是将文本复制为具有不同文本颜色的两层,然后我使用通过鼠标移动调整的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>

Here is Another idea using radial-gradient and without duplicating the text that can work with multiple elements at the same time:这是使用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>

Related question with similar ideas: Stacking circles produces a black bar on border radius具有类似想法的相关问题:堆叠圆在边界半径上产生黑条

Made a solution using mix-blend-mode: difference;使用mix-blend-mode: difference;做了一个解决方案mix-blend-mode: difference; for the .cursor .对于.cursor

The advantage is - we don't need to add any classes or javascript to all elements that we are hovering with our circle-mouse over.优点是 - 我们不需要向我们用圆形鼠标悬停的所有元素添加任何类或 javascript。

The disadvantage is - this solution less stable due to mix-blend-mode is a bit raw technology.缺点是 - 由于mix-blend-mode这种解决方案不太稳定,有点原始技术。 It requires to set height in body and html , and strict background-color for body .它需要在bodyhtml设置height ,并为body设置严格的background-color

The part with .cursor CSS and JavaScript - I partly borrowed form the solution of @Temani Afif.带有.cursor CSS 和 JavaScript 的部分 - 我部分借用了@Temani Afif 的解决方案。 Thank you and hope you don't mind, because it's pointless to try to write it better.谢谢你,希望你不要介意,因为试图把它写得更好是没有意义的。 But i added +window.scrollX and +window.scrollY for correct .cursor work while scrolling.但是我在滚动时添加了+window.scrollX+window.scrollY以确保正确的.cursor工作。

More about mix-blend-mode you cay read here https://caniuse.com/#search=mix-blend-mode andhttps://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode更多关于mix-blend-mode你可以在这里阅读https://caniuse.com/#search=mix-blend-modehttps://developer.mozilla.org/en-US/docs/Web/CSS/mix-混合模式

 document.body.onmousemove = function(e) { document.documentElement.style.setProperty('--x', (e.clientX+window.scrollX) + 'px'); document.documentElement.style.setProperty('--y', (e.clientY+window.scrollY) + 'px'); }
 html { height: 100%; /* requires for stable body height */ } body { min-height: 100%; /* requires for 'mix-blend-mode' */ cursor: none; color: #000; background-color: #fff; /* requires for 'mix-blend-mode' */ } .cursor { position: absolute; width: 40px; height: 40px; background: #fff; border-radius: 50%; top: var(--y, 0); left: var(--x, 0); transform: translate(-50%, -50%); z-index: 2; mix-blend-mode: difference; }
 <h1>WORK</h1> <span class="cursor"></span>

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

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