Радужный свет при наведении на кнопку

Разработка Радужный свет при наведении на кнопку

Нет прав для скачивания
Радужный свет при наведении на кнопку.
Пишем разметку:
Код:
<button class="prism">Click Me</button>
<button class="prism">Click Me</button>
Пишем стиль для разметки:
SCSS:
.prism {
  --intensity: 1;
  --scaleFactor: 1.01;
  --blur: 5;
  --redTop: 0;
  --redLeft: 0;
  --greenTop: 0;
  --greenLeft: 0;
  --blueTop: 0;
  --blueLeft: 0;
  position: relative;
  top: 0;
  color: var(--fg);
  background: var(--bg);
  border: 2px solid #333;
  transition: border-color 0.2s linear, top 0.1s ease;
 
  & > .red, & > .green, & > .blue {
    position: absolute;
    width: calc(var(--scaleFactor) * 100%);
    height: calc(var(--scaleFactor) * 100%);
    z-index: -1;
    border-radius: inherit;
    filter: blur(calc(var(--blur) * 1px));
    mix-blend-mode: screen;
    opacity: var(--intensity);
  }
  & > .red {
    top: calc(var(--redTop) * 1px);
    left: calc(var(--redLeft) * 1px);
    background: rgb(255, 0, 0);
  }
  & > .green {
    top: calc(var(--greenTop) * 1px);
    left: calc(var(--greenLeft) * 1px);
    background: rgb(0, 255, 0);
  }
  & > .blue {
    top: calc(var(--blueTop) * 1px);
    left: calc(var(--blueLeft) * 1px);
    background: rgb(0, 0, 255);
  }
  &:focus {
    outline: none;
    border-color: #fff;
  }
  &:active {
    top: -4px;
  }
}
button {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: none;
  border-radius: var(--border-radius, 100em);
  padding: 1em 2em;
  font-weight: bolder;
  &:hover {
    cursor: pointer; 
  }
  & + button {
    margin-left: 1em;
  }
}
body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
}
:root {
  --bg: #222;
  --fg: #fff;
  --border-radius: 9em;
  font-size: 30px;
}
Пишем js:
JavaScript:
const buttons = document.querySelectorAll(".prism");
let center = vec2.fromValues(innerWidth * 0.5, innerHeight * 0.5);
let mousePos = vec2.clone(center);
const minDist = 0;
const maxDist = 400;
const minOffset = 0;
const maxOffset = 25;
const rotationalScale = 1;
const TAU = Math.PI * 2;

function handleMouseMove(event) {
  vec2.set(mousePos, event.clientX, event.clientY);
  const angle = mousePos[0] * mousePos[1] * 0.00005;
 
  // Get the distance of each button to the mouse
  buttons.forEach(button => {
    const rect = button.getBoundingClientRect();
    if(isOnScreen(rect)) {
      const buttonCenter = vec2.fromValues(
        rect.left + (rect.right - rect.left) * 0.5,
        rect.top + (rect.bottom - rect.top) * 0.5,
      );
      const distValue = vec2.dist(buttonCenter, mousePos);
      const dist = clamp(distValue, minDist, maxDist);
      const offset = map(maxDist - dist, minDist, maxDist, maxOffset, minOffset);
      const intensity = map(maxDist - dist, 0, maxDist, 0, 1);
      button.style.setProperty('--intensity', intensity * intensity);
      const scaleFactor = map(maxDist - dist, 0, maxDist, 1.01, 1.05);
      const offsetCorrection = map(maxDist - dist, 0, maxDist, 0, maxOffset * 0.5);
      button.style.setProperty('--scaleFactor', scaleFactor);
      const blur = map(dist, 0, maxDist, 5, 50);
      button.style.setProperty('--blur', blur);
      
      const redTopValue = Math.sin((angle + 0) * rotationalScale) * offset - offsetCorrection * -0.19;
      const redLeftValue = Math.cos((angle + 0) * rotationalScale) * offset - offsetCorrection;
      button.style.setProperty('--redTop', redTopValue);
      button.style.setProperty('--redLeft', redLeftValue);
      
      const greenTopValue = Math.sin((angle + 2) * rotationalScale) * offset - offsetCorrection * 0.5;
      const greenLeftValue = Math.cos((angle + 2) * rotationalScale) * offset - offsetCorrection * 0.5;
      button.style.setProperty('--greenTop', greenTopValue);
      button.style.setProperty('--greenLeft', greenLeftValue);
      
      const blueTopValue = Math.sin((angle + 4) * rotationalScale) * offset - offsetCorrection;
      const blueLeftValue = Math.cos((angle + 4) * rotationalScale) * offset - offsetCorrection;
      button.style.setProperty('--blueTop', blueTopValue);
      button.style.setProperty('--blueLeft', blueLeftValue);
    }
  });
 
}
addEventListener("mousemove", throttled(handleMouseMove));

function handleResize() {
  vec2.set(center, innerWidth * 0.5, innerHeight * 0.5);
}
addEventListener("resize", throttled(handleResize));

function init() {
  buttons.forEach(button => {
    button.innerHTML = `<span class='red'></span><span class='green'></span><span class='blue'></span>${button.innerHTML}`;
  });
}
init();

// USEFUL FUNCTIONS -----------------
function throttled(fn) {
  let didRequest = false;
  return param => {
    if (!didRequest) {
      window.requestAnimationFrame(() => {
        fn(param);
        didRequest = false;
      });
      didRequest = true;
    }
  };
}
function isOnScreen(rect) {
   return rect.top < window.innerHeight && rect.bottom > 0;
}
function clamp(value, min = 0, max = 1) {
  return value <= min ? min : value >= max ? max : value;
}
function map(value, min1, max1, min2, max2) {
  return (value - min1) * (max2 - min2) / (max1 - min1) + min2;
}
Смотрим наш результат:
fg53.gif
Автор
baltun
Скачиваний
0
Просмотры
595
Первый выпуск
Обновление
Рейтинг
0.00 звёзд Оценок: 0

Ещё ресурсы от baltun

Похожие ресурсы
Назад
Верх Низ