0
I’d like to use this effect on one of my projects.
const ui = {
	btn: document.querySelector('.c-magnetic-btn')
}
const state = {
	bounds: ui.btn.getBoundingClientRect(),
	threshold: parseInt(ui.btn.dataset.threshold),
	ratio: parseInt(ui.btn.dataset.ratio),
	isMagnetic: false,
	mouse: {
		x: 0,
		y: 0
	},
	ease: {
		x: 0,
		y: 0,
		scale: 1,
		value: ui.btn.dataset.ease
	},
	transform: {
		x: 0,
		y: 0,
		scale: 1,
		max: ui.btn.dataset.max
	},
	width: window.innerWidth,
	height: window.innerHeight,
	history: false,
	scale: ui.btn.dataset.scale
}
const mouseMove = ({ pageX, pageY }) => {
	Object.assign(state, {
		mouse: {
			x: pageX,
			y: pageY
		},
		isMagnetic: isMagnetic(pageX, pageY)
	})
}
const resize = () => {
	Object.assign(state, {
		bounds: ui.btn.getBoundingClientRect(),
		width: window.innerWidth,
		height: window.innerHeight
	})
}
const isMagnetic = (x, y) => {
	const { bounds } = state
	
	const centerX = bounds.left + (bounds.width / 2)
	const centerY = bounds.top + (bounds.height / 2)
	
	// use pythagorean theorem to calculate
	// cursor distance from center of btn
	// a^2 + b^2 = c^2
	const a = Math.abs(centerX - x)
	const b = Math.abs(centerY - y)
	const c = Math.sqrt(a * a + b * b)
	
	// true if cursor distance from center of btn is
	// equal to btn radius + threshold
	const isHover = c < (bounds.width / 2) + state.threshold
	if (!state.history && isHover) {
		ui.btn.classList.add('is-hover')
		Object.assign(state, {
			threshold: state.threshold * state.ratio,
			history: true
		})
	} else if (state.history && !isHover) {
		ui.btn.classList.remove('is-hover')
		Object.assign(state, {
			threshold: state.threshold / state.ratio,
			history: false
		})
	}
	return isHover
}
const run = () => {
	requestAnimationFrame(run)
	
	const { isMagnetic, transform, mouse, width, height, ease, max, scale } = state
	transform.x = isMagnetic ? (mouse.x - width / 2) / width * transform.max : 0
  transform.y = isMagnetic ? (mouse.y - height / 2) / height * transform.max : 0
	transform.scale = isMagnetic ? scale : 1
	
	// basic linear interpolation
	// https://www.youtube.com/watch?v=yWhgniVHROw
	ease.x += (transform.x - ease.x) * ease.value
	ease.y += (transform.y - ease.y) * ease.value
	ease.scale += (transform.scale - ease.scale) * ease.value
	Object.assign(ui.btn.style, {
		transform: `
			translate(
				${ease.x.toFixed(2)}px,
				${ease.y.toFixed(2)}px
			)
			translateZ(0)
			scale(
				${(ease.scale).toFixed(2)}
			)`
	})
}
const init = () => {
	document.addEventListener('mousemove', mouseMove)
	window.addEventListener('resize', resize)
	run()
}
init()* {
  box-sizing: border-box;
}
html,
body {
  height: 100%;
  margin: 0;
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
}
button {
  border: none;
  margin: 0;
  padding: 0;
  width: auto;
  overflow: visible;
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: normal;
  text-align: center;
  text-decoration: none;
  outline: none;
  cursor: pointer;
  white-space: normal;
  -webkit-font-smoothing: inherit;
  -moz-osx-font-smoothing: inherit;
  -webkit-appearance: none;
}
.u-fit {
  width: 100%;
  height: 100%;
}
.u-relative {
  position: relative;
}
.u-absolute {
  position: absolute;
}
.u-absolute.u-pos-tl {
  top: 0;
  left: 0;
}
.u-flex {
  display: flex;
}
.u-flex.u-center-xy {
  justify-content: center;
  align-items: center;
}
.c-magnetic-btn {
  width: 120px;
  height: 120px;
  border-radius: 50%;
}
.o-circle {
  display: inline-block;
  background-color: rgba(0, 0, 0, 0.015);
  border: 2px solid rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  z-index: -1;
  opacity: 0.2;
  transition: opacity 0.6s cubic-bezier(0.23, 1, 0.32, 1);
  will-change: opacity;
}
.t-btn-label {
  display: inline-block;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  font-family: 'Karla', sans-serif;
  font-weight: 700;
  letter-spacing: 1px;
  line-height: 1;
  color: rgba(0, 0, 0, 0.5);
  font-size: 13px;
}
.is-hover .o-circle {
  opacity: 0.4;
}<button class="c-magnetic-btn u-relative" 
				data-threshold="60" 
				data-ratio="3.5"
				data-max="100"
				data-scale="1.1"
				data-ease="0.225">
	<span class="t-btn-label u-flex u-center-xy">Hover me.</span>
	<span class="o-circle u-fit u-absolute u-pos-tl"></span>
</button>I don’t understand much of javascript, and the effect itself is all done with javascript, I would need help to use this effect on as many buttons/ elements as I want, I believe I have how to do this. I believe it is just some change in javascript, could help me in this?
Thanks Cristiano! Solve my problem!
– Lucas Granvilla