Mix-Blend mode doesn't work on custom cursor

248
January 01, 2020, at 10:20 PM

I would like to add a mix-blend-mode: difference to the inner cursor, but I can't get it to work. I heard that the position: fixed applied to the cursor may cause the problem here. But I can't remove that property, because the cursor needs to follow when scrolling down. Does anyone know how to fix the problem here? Thank you in advance.

class Demo { 
  constructor() { 
    this.initCursor(); 
    this.initHovers(); 
  } 
  
 
  initCursor() { 
    const { Back } = window; 
    this.outerCursor = document.querySelector(".circle-cursor-outer"); 
    this.innerCursor = document.querySelector(".circle-cursor-inner"); 
    this.outerCursorBox = this.outerCursor.getBoundingClientRect(); 
    this.outerCursorSpeed = 0; 
    this.easing = Back.easeOut.config(1.7); 
    this.clientX = -100; 
    this.clientY = -100; 
    this.showCursor = false; 
 
    const unveilCursor = () => { 
      TweenMax.set(this.innerCursor, { 
        x: this.clientX, 
        y: this.clientY 
      }); 
      TweenMax.set(this.outerCursor, { 
        x: this.clientX - this.outerCursorBox.width / 2, 
        y: this.clientY - this.outerCursorBox.height / 2 
      }); 
      setTimeout(() => { 
        this.outerCursorSpeed = 0.2; 
      }, 100); 
      this.showCursor = true; 
    }; 
    document.addEventListener("mousemove", unveilCursor); 
 
    document.addEventListener("mousemove", e => { 
      this.clientX = e.clientX; 
      this.clientY = e.clientY; 
    }); 
 
    const render = () => { 
      TweenMax.set(this.innerCursor, { 
        rotation: 90, 
        x: this.clientX, 
        y: this.clientY 
      }); 
      if (!this.isStuck) { 
        TweenMax.to(this.outerCursor, this.outerCursorSpeed, { 
          x: this.clientX - this.outerCursorBox.width / 2, 
          y: this.clientY - this.outerCursorBox.height / 2 
        }); 
      } 
      if (this.showCursor) { 
        document.removeEventListener("mousemove", unveilCursor); 
      } 
      requestAnimationFrame(render); 
    }; 
    requestAnimationFrame(render); 
  } 
 
  initHovers() { 
    const handleMouseEnter = e => { 
      this.isStuck = true; 
      const target = e.currentTarget; 
      const box = target.getBoundingClientRect(); 
      this.outerCursorOriginals = { 
        width: this.outerCursorBox.width, 
        height: this.outerCursorBox.height 
      }; 
      TweenMax.to(this.innerCursor, 0.2, { 
        x: box.left, 
        y: box.top, 
        width: box.width, 
        height: box.height, 
        opacity: 0.4, 
      }); 
    }; 
 
    const handleMouseLeave = () => { 
      this.isStuck = false; 
      TweenMax.to(this.innerCursor, 0.2, { 
        width: this.outerCursorOriginals.width, 
        height: this.outerCursorOriginals.height, 
        opacity: 0.2, 
      }); 
    }; 
 
    const mainNavHoverTween = TweenMax.to(this.innerCursor, 0.3, { 
      ease: this.easing, 
      paused: true, 
      opacity: 1, 
      width: 70, 
      height: 70, 
      left: -35, 
      top: -35 
    }); 
 
    const mainNavMouseEnter = () => { 
      this.outerCursorSpeed = 0; 
      TweenMax.set(this.innerCursor, { opacity: 1 }); 
      mainNavHoverTween.play(); 
    }; 
 
    const mainNavMouseLeave = () => { 
      this.outerCursorSpeed = 0.2; 
      TweenMax.set(this.innerCursor, { opacity: 1 }); 
      mainNavHoverTween.reverse(); 
    }; 
 
    const mainNavLinks = document.querySelectorAll("a"); 
    mainNavLinks.forEach(item => { 
      item.addEventListener("mouseenter", mainNavMouseEnter); 
      item.addEventListener("mouseleave", mainNavMouseLeave); 
    }); 
 
   
 
 
 
 
 
 
 
  } 
} 
 
const demo = new Demo();
body{ 
  height: 500vh; 
} 
 
a{ 
  color: black; 
} 
 
.circle-cursor { 
  position: fixed; 
  left: 0; 
  top: 0; 
  pointer-events: none; 
  border-radius: 100%; 
} 
.circle-cursor-outer-badge { 
  opacity: 0.5; 
  transition: all 500ms ease-out; 
} 
.circle-cursor-inner { 
  width: 22.5px; 
  height: 22.5px; 
  left: -11.25px; 
  top: -11.25px; 
  z-index: 11000; 
  mix-blend-mode: difference; 
  background-color: black; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<body> 
  <a href="#">I am a link</a> 
  <div class="circle-cursor circle-cursor-outer"> 
    <img class="circle-cursor-outer-badge" draggable="false" width="120" src="https://svgshare.com/i/H2V.svg"> 
  </div> 
  <div class="circle-cursor circle-cursor-inner"></div> 
</body>

Answer 1

Just set background:white to both body and .circle-cursor-inner:

class Demo { 
  constructor() { 
    this.initCursor(); 
    this.initHovers(); 
  } 
  
 
  initCursor() { 
    const { Back } = window; 
    this.outerCursor = document.querySelector(".circle-cursor-outer"); 
    this.innerCursor = document.querySelector(".circle-cursor-inner"); 
    this.outerCursorBox = this.outerCursor.getBoundingClientRect(); 
    this.outerCursorSpeed = 0; 
    this.easing = Back.easeOut.config(1.7); 
    this.clientX = -100; 
    this.clientY = -100; 
    this.showCursor = false; 
 
    const unveilCursor = () => { 
      TweenMax.set(this.innerCursor, { 
        x: this.clientX, 
        y: this.clientY 
      }); 
      TweenMax.set(this.outerCursor, { 
        x: this.clientX - this.outerCursorBox.width / 2, 
        y: this.clientY - this.outerCursorBox.height / 2 
      }); 
      setTimeout(() => { 
        this.outerCursorSpeed = 0.2; 
      }, 100); 
      this.showCursor = true; 
    }; 
    document.addEventListener("mousemove", unveilCursor); 
 
    document.addEventListener("mousemove", e => { 
      this.clientX = e.clientX; 
      this.clientY = e.clientY; 
    }); 
 
    const render = () => { 
      TweenMax.set(this.innerCursor, { 
        rotation: 90, 
        x: this.clientX, 
        y: this.clientY 
      }); 
      if (!this.isStuck) { 
        TweenMax.to(this.outerCursor, this.outerCursorSpeed, { 
          x: this.clientX - this.outerCursorBox.width / 2, 
          y: this.clientY - this.outerCursorBox.height / 2 
        }); 
      } 
      if (this.showCursor) { 
        document.removeEventListener("mousemove", unveilCursor); 
      } 
      requestAnimationFrame(render); 
    }; 
    requestAnimationFrame(render); 
  } 
 
  initHovers() { 
    const handleMouseEnter = e => { 
      this.isStuck = true; 
      const target = e.currentTarget; 
      const box = target.getBoundingClientRect(); 
      this.outerCursorOriginals = { 
        width: this.outerCursorBox.width, 
        height: this.outerCursorBox.height 
      }; 
      TweenMax.to(this.innerCursor, 0.2, { 
        x: box.left, 
        y: box.top, 
        width: box.width, 
        height: box.height, 
        opacity: 0.4, 
      }); 
    }; 
 
    const handleMouseLeave = () => { 
      this.isStuck = false; 
      TweenMax.to(this.innerCursor, 0.2, { 
        width: this.outerCursorOriginals.width, 
        height: this.outerCursorOriginals.height, 
        opacity: 0.2, 
      }); 
    }; 
 
    const mainNavHoverTween = TweenMax.to(this.innerCursor, 0.3, { 
      ease: this.easing, 
      paused: true, 
      opacity: 1, 
      width: 70, 
      height: 70, 
      left: -35, 
      top: -35 
    }); 
 
    const mainNavMouseEnter = () => { 
      this.outerCursorSpeed = 0; 
      TweenMax.set(this.innerCursor, { opacity: 1 }); 
      mainNavHoverTween.play(); 
    }; 
 
    const mainNavMouseLeave = () => { 
      this.outerCursorSpeed = 0.2; 
      TweenMax.set(this.innerCursor, { opacity: 1 }); 
      mainNavHoverTween.reverse(); 
    }; 
 
    const mainNavLinks = document.querySelectorAll("a"); 
    mainNavLinks.forEach(item => { 
      item.addEventListener("mouseenter", mainNavMouseEnter); 
      item.addEventListener("mouseleave", mainNavMouseLeave); 
    }); 
 
   
 
 
 
 
 
 
 
  } 
} 
 
const demo = new Demo();
body{ 
  height: 500vh;  
  background:white; 
} 
 
a{ 
  color: black; 
} 
 
.circle-cursor { 
  position: fixed; 
  left: 0; 
  top: 0; 
  pointer-events: none; 
  border-radius: 100%; 
} 
.circle-cursor-outer-badge { 
  opacity: 0.5; 
  transition: all 500ms ease-out; 
} 
.circle-cursor-inner { 
  width: 22.5px; 
  height: 22.5px; 
  left: -11.25px; 
  top: -11.25px; 
  z-index: 11000; 
  mix-blend-mode: difference; 
  background: white; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<body> 
  <a href="#">I am a link</a> 
  <div class="circle-cursor circle-cursor-outer"> 
    <img class="circle-cursor-outer-badge" draggable="false" width="120" src="https://svgshare.com/i/H2V.svg"> 
  </div> 
  <div class="circle-cursor circle-cursor-inner"></div> 
</body>

READ ALSO
HTML, CSS, JavaScript modal and many pages

HTML, CSS, JavaScript modal and many pages

I have an HTML page that has a modal popup window on itThe page has Javascript and CSS and works fine

90
CSS Emotion is caching CSS despite variables

CSS Emotion is caching CSS despite variables

I'm using Emotion for CSS in a React projectIt's working correctly but I have one component that uses the css property with JS arguments and it seems Emotion is caching the CSS despite the variables changes

78
smooth transition on content change

smooth transition on content change

I have a DIV of unknown height with content that can be changed from a javascript eventWhen the content changes, the DIV resizes to fit the new content

115