【问题标题】:Custom Cursor that invert colors反转颜色的自定义光标
【发布时间】:2019-03-10 21:38:39
【问题描述】:

我有一个问题。 如何制作一个光标来还原其背后的颜色并应用于自身。

就像“负面”效应。

但我需要它是自动的,无需对每种颜色进行编码,因此它可以与自身背后的任何元素进行交互。

这是我的自定义光标的开始和我的背景可以是什么的一个例子:

(function () {
  var follower, init, mouseX, mouseY, positionElement, printout, timer;

  follower = document.getElementById('follower');

  printout = document.getElementById('printout');

  mouseX = event => {
    return event.clientX;
  };

  mouseY = event => {
    return event.clientY;
  };

  positionElement = event => {
    var mouse;
    mouse = {
      x: mouseX(event),
      y: mouseY(event) };

    follower.style.top = mouse.y + 'px';
    return follower.style.left = mouse.x + 'px';
  };

  timer = false;

  window.onmousemove = init = event => {
    var _event;
    _event = event;
    return timer = setTimeout(() => {
      return positionElement(_event);
    }, 1);
  };

}).call(this);

//# sourceURL=coffeescript
* {
  cursor: none;
  margin:0;
  padding:0;
}

.img{
  width:49vw;
  height:99vh;
  position:absolute;
  background: url('https://images.pexels.com/photos/531880/pexels-photo-531880.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=1000');
}
.img2{
  width:49vw;
  height:99vh;
  left:49vw;
  position:absolute;
  background: url('https://cdn-images-1.medium.com/max/1600/0*I-sI3u34g0ydRqyA');
}

#follower {
  position: absolute;
  top: 50%;
  left: 50%;
}
#follower #circle {
  position: absolute;
  background: #fff;
  border-radius: 50%;
  opacity: 0.5;
  height: 1.5em;
  width: 1.5em;
  margin-top: -0.5em;
  margin-left: -0.5em;
  z-index:2;
}
<div id="follower">
  <div id="circle"></div>
</div>

<div class="img"></div>
<div class="img2"></div>

如何给光标带来负面影响?

【问题讨论】:

    标签: javascript html css colors mouse-cursor


    【解决方案1】:

    这是一个使用背景的想法,其中诀窍是使用radial-gradient 模拟光标,以便您可以根据需要定义每个元素的颜色:

    document.onmousemove = function(e) {
      document.body.style.setProperty('--x',(e.clientX)+'px');
      document.body.style.setProperty('--y',(e.clientY)+'px');
      
    }
    * {
      cursor: none;
      margin:0;
      padding:0;
    }
    
    .red{
      width:33vw;
      height:100vh;
      position:absolute;
      background:
      radial-gradient(farthest-side ,white 95%,transparent 100%)
        calc(var(--x) - .75em) calc(var(--y) - .75em)/ /*position*/
        1.5em 1.5em   /*size of circle*/
        fixed no-repeat;
      background-color:red;
    }
    .black{
      width:33vw;
      height:100vh;
      margin-left:33vw;
      position:absolute;
      background:radial-gradient(farthest-side ,cyan 95%,transparent 100%)
        calc(var(--x) - .75em) calc(var(--y) - .75em)/1.5em 1.5em  fixed no-repeat;
      background-color:black;
    }
    .green{
      width:33vw;
      height:100vh;
      margin-left:66vw;
      position:absolute;
      background:radial-gradient(farthest-side ,blue 95%,transparent 100%)
        calc(var(--x) - .75em) calc(var(--y) - .75em)/1.5em 1.5em  fixed no-repeat;
      background-color:green;
    }
    <div class="red"></div>
    <div class="black"></div>
    <div class="green"></div>

    诀窍是每个渐变都是fixed,因此它相对于视口定位,然后我对所有渐变使用相同的 CSS 变量将它们放置在相同的位置。每个将仅在其部分中可见。

    如果您有内容并且需要将光标置于所有内容之上,您可以考虑使用伪元素在顶部创建图层:

    document.onmousemove = function(e) {
      document.body.style.setProperty('--x',(e.clientX)+'px');
      document.body.style.setProperty('--y',(e.clientY)+'px');
      
    }
    * {
      cursor: none;
      margin:0;
      padding:0;
    }
    .box {
      position:relative;
      z-index:0;
      color:#fff;
    }
    .box:before {
      content:"";
      position:absolute;
      z-index:999;
      top:0;
      left:0;
      right:0;
      bottom:0; 
      background:
      radial-gradient(farthest-side ,var(--c) 95%,transparent 100%)
        calc(var(--x) - .75em) calc(var(--y) - .75em)/1.5em 1.5em  fixed no-repeat;
    }
    
    
    .red{
      width:33vw;
      height:100vh;
      position:absolute;
      background-color:red;
      --c:white;
    }
    .black{
      width:33vw;
      height:100vh;
      margin-left:33vw;
      position:absolute;
      background-color:black;
      --c:cyan;
    }
    .green{
      width:33vw;
      height:100vh;
      margin-left:66vw;
      position:absolute;
      background-color:green;
      --c:blue;
    }
    <div class="red box">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin molestie sem non dui tempus placerat non ut nulla. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In vel nulla commodo, dignissim sem in, viverra ipsum. Nam non libero neque.</div>
    <div class="black box">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin molestie sem non dui tempus placerat non ut nulla. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In vel nulla commodo, dignissim sem in, viverra ipsum. Nam non libero neque.</div>
    <div class="green box">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin molestie sem non dui tempus placerat non ut nulla. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In vel nulla commodo, dignissim sem in, viverra ipsum. Nam non libero neque.</div>

    这是另一个想法,您可以使用与您的 3 个部分具有相同尺寸的 linear-gradient 为您制作的光标着色:

    (function () {
      var follower, init, mouseX, mouseY, positionElement, printout, timer;
    
      follower = document.getElementById('follower');
    
      printout = document.getElementById('printout');
    
      mouseX = event => {
        return event.clientX;
      };
    
      mouseY = event => {
        return event.clientY;
      };
    
      positionElement = event => {
        var mouse;
        mouse = {
          x: mouseX(event),
          y: mouseY(event) };
    
        follower.style.top = mouse.y + 'px';
        return follower.style.left = mouse.x + 'px';
      };
    
      timer = false;
    
      window.onmousemove = init = event => {
        var _event;
        _event = event;
        return timer = setTimeout(() => {
          return positionElement(_event);
        }, 1);
      };
    
    }).call(this);
    
    //# sourceURL=coffeescript
    * {
      cursor: none;
      margin:0;
      padding:0;
    }
    
    .red{
      width:33vw;
      height:100vh;
      position:absolute;
      background-color:red;
    }
    .black{
      width:33vw;
      height:100vh;
      margin-left:33vw;
      position:absolute;
      background-color:black;
    }
    .green{
      width:33vw;
      height:100vh;
      margin-left:66vw;
      position:absolute;
      background-color:green;
    }
    
    #follower {
      position: absolute;
      top: 50%;
      left: 50%;
    }
    #follower #circle {
      position: absolute;
      background:
        linear-gradient(white,white) 0  0,
        linear-gradient(cyan,cyan) 33vw 0,
        linear-gradient(blue,blue) 66vw 0;
      background-size:33vw 100vh;
      background-attachment:fixed;
      background-repeat:no-repeat;
      border-radius: 50%;
      opacity: 0.5;
      height: 1.5em;
      width: 1.5em;
      margin-top: -0.5em;
      margin-left: -0.5em;
      z-index:2;
    }
    <div id="follower">
      <div id="circle"></div>
    </div>
    
    <div class="red"></div>
    <div class="black"></div>
    <div class="green"></div>

    上述代码相关部分:

     background:
        linear-gradient(white,white) 0  0,
        linear-gradient(cyan,cyan) 33vw 0,
        linear-gradient(blue,blue) 66vw 0;
     background-size:33vw 100vh;
     background-attachment:fixed;
     background-repeat:no-repeat;
    

    更新

    根据你的新需求,可以考虑mix-blend-mode实现你想要的

    document.onmousemove = function(e) {
      document.body.style.setProperty('--x',(e.clientX)+'px');
      document.body.style.setProperty('--y',(e.clientY)+'px');
      
    }
    * {
      cursor: none;
      margin:0;
      padding:0;
    }
    .box {
      position:relative;
      z-index:0;
      color:#fff;
    }
    .box:before {
      content:"";
      position:absolute;
      z-index:999;
      top:0;
      left:0;
      right:0;
      bottom:0; 
      background:
      radial-gradient(farthest-side ,#fff 95%,transparent 100%)
        calc(var(--x) - .75em) calc(var(--y) - .75em)/1.5em 1.5em  fixed no-repeat;
      mix-blend-mode:difference;
    }
    
    
    .red{
      width:33vw;
      height:100vh;
      position:absolute;
      background-color:red;
    }
    .black{
      width:33vw;
      height:100vh;
      margin-left:33vw;
      position:absolute;
      background:url(https://picsum.photos/800/600?image=1069) center/cover;
    }
    .green{
      width:33vw;
      height:100vh;
      margin-left:66vw;
      position:absolute;
      background:url(https://picsum.photos/800/600?image=1039) center/cover;
    }
    <div class="red box"></div>
    <div class="black box"></div>
    <div class="green box"></div>

    您只需更改光标颜色(一次)并定义所需的混合模式。

    这里是光标元素:

    document.onmousemove = function(e) {
      document.body.style.setProperty('--x',(e.clientX)+'px');
      document.body.style.setProperty('--y',(e.clientY)+'px');
      
    }
    * {
      cursor: none;
      margin:0;
      padding:0;
    }
    body:before {
      content:"";
      position:absolute;
      z-index:999;
      top:var(--y);
      left:var(--x);
      right:0;
      bottom:0; 
      width:1.5em;
      height:1.5em;
      border-radius:50%;
      transform:translate(-50%,-50%);
      background:#fff;
      mix-blend-mode:difference;
    }
    
    
    .red{
      width:33vw;
      height:100vh;
      position:absolute;
      background-color:red;
    }
    .black{
      width:33vw;
      height:100vh;
      margin-left:33vw;
      position:absolute;
      background:url(https://picsum.photos/800/600?image=1069) center/cover;
    }
    .green{
      width:33vw;
      height:100vh;
      margin-left:66vw;
      position:absolute;
      background:url(https://picsum.photos/800/600?image=1039) center/cover;
    }
    <div class="red box"></div>
    <div class="black box"></div>
    <div class="green box"></div>

    【讨论】:

    • 感谢您的回答。它将帮助我完成其他项目,但我需要动态执行,因为我的网站上有图像。我提出的代码只是一个例子,但任何代码都对我有好处,我只是希望光标变成一个反转它背后颜色的圆圈
    • @TutOzz 你能更精确地了解你想要的动态部分吗?
    • 我在第一篇文章中编辑了我的代码以便更好地理解。我需要圆圈像一个负面过滤器一样,我不能只对每种颜色进行编码,因为我的页面中有图像和很多元素。光标需要在任何地方可见,所以我只希望它应用“负面”效果。所以,你回答我的代码是正确的,但我需要一种方法来自动和在图像上完成它
    • @TutOzz 检查上次更新日期
    • 如果您使用一个元素作为光标,请确保使用pointer-events: none,这样它就不会阻止来自其他元素的点击或悬停事件
    【解决方案2】:

    扩展 Temani Afif 的回答:

    如果您必须滚动,他的代码会中断,因为绘制的光标位置与实际光标位置相差您滚动的量。

    您可以将document.documentElement.scrollTop 添加到 y 值,但光标不会在滚动时更新。

    除了onmousemove之外,您还可以调用函数来更新--x--y属性onscroll,但是,onscroll事件没有e.clientXe.clientY,所以这些值被计算为 0 并且光标位置偏离了。

    为了解决这个问题,我缓存了最新鼠标移动的 x 和 y 值,然后使用使用缓存的 x 和 y 值并添加 @987654329 的函数更新鼠标移动和滚动时的属性@ 到 y 值:

    let x, y;
    
    document.onmousemove = function(e) {
        x = e.clientX;
        y = e.clientY;
        updateProps();
    };
    
    document.onscroll = updateProps;
    
    function updateProps() {
        document.body.style.setProperty('--x',(x)+'px');
        document.body.style.setProperty('--y',(y + document.documentElement.scrollTop)+'px');
    }
    

    【讨论】:

      猜你喜欢
      • 2022-08-12
      • 2020-02-20
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多