【问题标题】:3D card hover effect in React Js3D card hover effect in React Js
【发布时间】:2022-12-26 17:03:00
【问题描述】:

I am trying to create 3D card hover effect in React but hover behaviour is different than in plain javascript.

I can not figure out why behaviour is different with same logic.

Plain Javascript demo: https://codepen.io/markmiro/pen/wbqMPa

<div class="card">
  3D Card
  <div class="glow" />
</div>
* {
  box-sizing: border-box;
}

html, body {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

body {
  font-family: system-ui, sans-serif;
  perspective: 1500px;
  background: linear-gradient(white, #efefef);
}

.card {
  font-weight: bold;
  padding: 1em;
  text-align: right;
  color: #181a1a;
  
  width:  300px;
  height: 400px;
  box-shadow: 0 1px 5px #00000099;
  
  border-radius: 10px;
  background-image: url(https://images.unsplash.com/photo-1557672199-6e8c8b2b8fff?ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80);
  background-size: cover;
  
  position: relative;
  
  transition-duration: 300ms;
  transition-property: transform, box-shadow;
  transition-timing-function: ease-out;
  transform: rotate3d(0);
}

.card:hover {
  transition-duration: 150ms;
  box-shadow: 0 5px 20px 5px #00000044;
}

.card .glow {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  
  background-image: radial-gradient(circle at 50% -20%, #ffffff22, #0000000f);
}
const $card = document.querySelector('.card');
let bounds;

function rotateToMouse(e) {
  const mouseX = e.clientX;
  const mouseY = e.clientY;
  const leftX = mouseX - bounds.x;
  const topY = mouseY - bounds.y;
  const center = {
    x: leftX - bounds.width / 2,
    y: topY - bounds.height / 2
  }
  const distance = Math.sqrt(center.x**2 + center.y**2);
  
  $card.style.transform = `
    scale3d(1.07, 1.07, 1.07)
    rotate3d(
      ${center.y / 100},
      ${-center.x / 100},
      0,
      ${Math.log(distance)* 2}deg
    )
  `;
  
 console.log(center.y / 100) ;$card.querySelector('.glow').style.backgroundImage = `
    radial-gradient(
      circle at
      ${center.x * 2 + bounds.width/2}px
      ${center.y * 2 + bounds.height/2}px,
      #ffffff55,
      #0000000f
    )
  `;
}

$card.addEventListener('mouseenter', () => {
  bounds = $card.getBoundingClientRect();
  document.addEventListener('mousemove', rotateToMouse);
});

$card.addEventListener('mouseleave', () => {
  document.removeEventListener('mousemove', rotateToMouse);
  $card.style.transform = '';
  $card.style.background = '';
});

React implementation: https://stackblitz.com/edit/react-eghmd8

I have changed all queryselectors with useRef hook.

【问题讨论】:

  • It looks like it might be because of height of the window, try having both demos open side by side, and resizing them so the output section is the same height. I seem to get slightly different behaviour when the height of the output panel is different

标签: javascript css reactjs react-hooks css-animations


【解决方案1】:

It seems that this property perspective: 1500px need to be added to the output container of the component for this to work.

Forked live example with the fix: stackblitz

Create a class with this in style.css:

.app {
  perspective: 1500px;
}

In App.js add the className to the output container:

  // ? Add the class here
  return (
    <div className="app">
      <div
        ref={inputRef}
        className="card"
        onMouseLeave={removeListener}
        onMouseMove={rotateToMouse}
      >
        3D Card
        <div ref={glowRef} className="glow" />
      </div>
    </div>
  );

There could be other issues need to be addressed but hope that this still help as a reference.

【讨论】:

    猜你喜欢
    • 2020-08-01
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    • 2022-12-20
    • 2018-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多