CSS - Custom cursor that changes depending on hovered element flickers when moving left to right but not right to left

天大地大妈咪最大 提交于 2020-01-25 09:28:09

问题


I am trying to create a custom cursor that changes when hovering over a <div>, but there is a flicker when moving left to right across it, but not when moving right to left. Why this is happening and what I can do to fix it?

document.addEventListener('mousemove', (ev) => cursorMove(ev));

function cursorMove(ev) {
  let circle = document.getElementById('circle');
  let posY = ev.clientY;
  let posX = ev.clientX;
  
  circle.style.top = posY + 'px';
  circle.style.left = posX + 'px';
}
body {
  margin: 0;
  height: 100vh;
  background-color: #acd1d2;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: monospace;
}

#wrapper {
  position: relative;
  width: 70%;
  height: 80%;
}

.box {
  height: 25%;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;  
}

#box-1 {
  background-color: #e8edf3;
}
  
#box-1:hover ~ #circle {
  background-color: #e6cf8b;
  box-shadow:inset 0em -0.3em 0.4em 0.2em #ca9e03a6;
}

#box-2 {
  background-color: #e6cf8b;
}
  
#box-2:hover ~ #circle {
  background-color: transparent;
  border: 3px solid #E91E63;
}

#box-3 {
  background-color: #b56969; 
}
  
#box-3:hover ~ #circle {
  height: 1em;
  width: 1em;
  background-color: #e6cf8b;
} 

#box-4 {
  background-color: #22264b;
  color: white;
}

#box-4:hover ~ #circle {
  background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
}  

#circle {
  position: fixed;
  border-radius: 50%;
  z-index: 5;
  height: 32px;
  width: 32px;
  background-color: white;
}
<div id="wrapper">
  <div id="box-1" class="box">Sphere</div>
  <div id="box-2" class="box">Circle outline</div>
  <div id="box-3" class="box">Circle pin</div>
  <div id="box-4" class="box">Circle color gradient</div>
  
  <div id="circle"></div>
</div>

回答1:


That's because your mouse moves faster than the circle and you hover over it, so the styles that apply to it are the same ones than when the cursor is on the background green/blue-ish area of the page.

You can fix that by adding pointer-events: none to the circle so that it feels a bit like this:

Ok, where were we? Oh yes... So you should use position: fixed instead of absolute (as you really want your cursor to be positioned relative to the top-left corner of the viewport) and probably window.requestAnimationFrame to get a smoother animation and translate3d(0, 0, 0) to promote the element to its own layer and enable hardware-accelerated rendering, which will also contribute to make it feel smoother.

You could also hide the default cursor with cursor: none and center the circle where the arrowhead of the cursor is to make it feel just like a real cursor.

const circle = document.getElementById('circle');
const circleStyle = circle.style;

document.addEventListener('mousemove', e => {
  window.requestAnimationFrame(() => {
    circleStyle.top = `${ e.clientY - circle.offsetHeight/2 }px`;
    circleStyle.left = `${ e.clientX - circle.offsetWidth/2 }px`;
  });
});
body {
  margin: 0;
  height: 100vh;
  background-color: #acd1d2;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: monospace;
  cursor: none;
}

#wrapper {
  position: relative;
  width: 70%;
  height: 80%;
}

#circle {
  position: fixed;
  border-radius: 50%;
  z-index: 5;
  height: 32px;
  width: 32px;
  background-color: white;
  pointer-events: none;
  transition:
    background ease-in 10ms,
    box-shadow ease-in 150ms,
    transform ease-in 150ms;
    
  /* Promote it to its own layer to enable  hardware accelerated rendering: */
  transform: translate3d(0, 0, 0);
}

.box {
  height: 25%;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;  
}

#box-1 {
  background-color: #e8edf3;
}
  
#box-1:hover ~ #circle {
  background-color: #e6cf8b;
  box-shadow: 0 0 0 0 transparent, inset 0em -0.3em 0.4em 0.2em #ca9e03a6;
}

#box-2 {
  background-color: #e6cf8b;
}
  
#box-2:hover ~ #circle {
  background-color: transparent;
  /* Use box-shadow instead of border to avoid changing the dimensions of the
     cursor, which will make it be off-center until the mouse moves again: */
  aborder: 3px solid #E91E63;
  box-shadow: 0 0 0 3px #E91E63;
}

#box-3 {
  background-color: #b56969; 
}
  
#box-3:hover ~ #circle {
  background-color: #e6cf8b;
  /* Change its size with scale() instead of width and height for better
     performance performance: */
  transform: scale(0.5) translate3d(0, 0, 0);
} 

#box-4 {
  background-color: #22264b;
  color: white;
}

#box-4:hover ~ #circle {
  background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
}  
<div id="wrapper">
  <div id="box-1" class="box">Sphere</div>
  <div id="box-2" class="box">Circle outline</div>
  <div id="box-3" class="box">Circle pin</div>
  <div id="box-4" class="box">Circle color gradient</div>
  
  <div id="circle"></div>
</div>

Here you can see another cool example I made of a custom cursor using CSS that resembles a torch: How to darken a CSS background image but keep area around cursor brighter.

Also, you can check out the cursor on my website, which is quite similar to what you have done as it has animations/transitions between its different shapes or states.

🚀 Check it out here: https://gmzcodes.com/.

👨‍💻 Check the code here: https://github.com/Danziger/gmzcodes



来源:https://stackoverflow.com/questions/50538768/css-custom-cursor-that-changes-depending-on-hovered-element-flickers-when-movi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!