.container
  .container__content
    .container__label Drag me!
  .container__proximity-wrap  
    .container__proximity
      .container__proximity-ring
View Compiled
*
  box-sizing border-box
  
body
  min-height 100vh
  font-weight bold
  font-size 1.15rem
  font-family sans-serif
  text-align center
  display grid
  place-items center
  background hsl(210, 50%, 50%)
  overflow hidden
  
.container
  height 135px
  width 135px
  position relative
  
  &__content
    background hsl(25, 50%, 80%)
    height 100%
    width 100%
    position absolute
    border-radius 50%
    z-index 2
    top 50%
    left 50%
    transform translate(-50%, -50%)
    display grid
    place-items center
  
  &__proximity
    resize horizontal
    min-width 200px
    overflow auto
    
  &__proximity-wrap
    position absolute
    top 50%
    left 50%
    transform translate(-50%, -50%)
    
  &__proximity-wrap:after
    content ''
    position absolute
    bottom 0
    right 0
    height 30px
    width 30px
    background hsl(180, 60%, 90%)
    $clip = $clip = polygon(0 100%, 100% 100%, 100% 0)
    clip-path $clip
    -webkit-clip-path $clip
    pointer-events none
    transform translate(2px, 2px)
    
  &__proximity-wrap:before
    content ''
    position absolute
    bottom 0
    right 0
    height 30px
    width 30px
    background hsl(180, 0%, 30%)
    $clip = polygon(0 100%, 100% 100%, 100% 0)
    clip-path $clip
    -webkit-clip-path $clip
    pointer-events none
    transform translate(6px, 6px)
    
  &__proximity-ring
    border-radius 50%
    aspect-ratio 1 / 1
    width 100%
    background hsla(0, 50%, 50%, 0.25)
  
  // &:after
  //   content ''
  //   position absolute
  //   top 50%
  //   left 50%
  //   height 200px
  //   width 200px
  //   border-radius 50%
  //   background hsla(280, 50%, 80%, 0.5)
  //   transform translate(-50%, -50%)
  //   z-index -1
View Compiled
import gsap from 'https://cdn.skypack.dev/gsap'
import Draggable from 'https://cdn.skypack.dev/gsap/Draggable'

gsap.registerPlugin(Draggable)

const CONTAINER = document.querySelector('.container')
const PROXIMITY = CONTAINER.querySelector('.container__proximity')
const LABEL = CONTAINER.querySelector('.container__label')

const generateHandler = (element, cb) => ({x, y}) => {
  const bounds = 100
  const elementBounds = element.getBoundingClientRect()
  const proximityBounds = PROXIMITY.getBoundingClientRect()
  const proximity = proximityBounds.width / 2
  const centerX = elementBounds.left + elementBounds.width / 2
  const centerY = elementBounds.top + elementBounds.height / 2
  const boundX = gsap.utils.mapRange(centerX - proximity, centerX + proximity, -bounds, bounds, x)
  const boundY = gsap.utils.mapRange(centerY - proximity, centerY + proximity, -bounds, bounds, y)
  cb(boundX / 100, boundY / 100)
}

document.addEventListener('pointermove', generateHandler(CONTAINER, (x, y) => {
  LABEL.innerText = `x: ${gsap.utils.clamp(-1, 1, x.toFixed(1))}; y: ${gsap.utils.clamp(-1, 1, y.toFixed(1))};`
}))

new Draggable(CONTAINER, {
  trigger: '.container__content'
})
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.