实现一个有意思的眼球跟随卡片

示例代码仓库:leixq1024/FrontEndSnippetHub: ✨html+css+js的前端特效合集

前言

​ 之前在figma上面浏览社区作品的时候,看到一个眼球跟随卡片,但是那个是用ai实现的,实现的代码有点长, 我觉得很繁琐,于是自己也做了一个类似的效果

最终效果

最终的效果如下

​

可以看到这里眼睛会跟着我的鼠标移动

因为页面比较简单,就不做过多介绍,主要讲眼球跟随的实现逻辑

实现逻辑

我定义了两个css变量

css 复制代码
:root {
  --eye-left: 0;
  --eye-top: 0;
}

黑色眼睛设置为绝对定位,并且top和left用这两个变量,这样我js部分只需要改变这两个变量即可

这里还有一个地方,我给眼睛外面套了一个div,这样做的目的是为了控制眼睛最大的可移动范围,根据父相子绝我可以轻松的显示眼球的活动范围

js部分如下

js 复制代码
const eye1 = document.querySelectorAll('.eye-pupils')[0]
const eye2 = document.querySelectorAll('.eye-pupils')[1]
let clientHeight = document.documentElement.clientHeight
let clientWidth = document.documentElement.clientWidth
window.addEventListener('mousemove', (e) => {
  requestAnimationFrame(() => {
    const { x, y } = e
    let left = (x / clientWidth) * 100
    let top = (y / clientHeight) * 100
    document.body.style.setProperty('--eye-left', `${left}%`)
    document.body.style.setProperty('--eye-top', `${top}%`)
  })
})
window.addEventListener('resize', () => {
  clientHeight = document.documentElement.clientHeight
  clientWidth = document.documentElement.clientWidth
})

let left = (x / clientWidth) * 100 let top = (y / clientHeight) * 100

这两句就是核心代码,通过计算鼠标的位置/页面的宽高就可以得到 当前的鼠标位置是在页面的哪个位置,并且是百分比的形式,这样我们只要将这个值更新到前面设置的css变量上面就可以实现眼球跟随移动

完整代码

html部分

html 复制代码
<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>眼球跟随卡片</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="card">
      <div class="eye-container">
        <div class="eye">
          <!-- 限制眼球的范围 -->
          <div class="eye-box">
            <div class="eye-pupils"></div>
          </div>
        </div>

        <div class="eye">
          <!-- 限制眼球的范围 -->
          <div class="eye-box">
            <div class="eye-pupils"></div>
          </div>
        </div>
      </div>
      <div class="info">
        <p>移动你的鼠标,看看卡片上的眼睛会如何"盯着"你!</p>
      </div>
    </div>
  </body>
  <script src="index.js"></script>
</html>

css部分

css 复制代码
:root {
  --bg-color: #0062ad;
  --eye-left: 0;
  --eye-top: 0;
}
html,
body {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-color);
}
.card {
  position: relative;
  width: 450px;
  background: #fff;
  padding: 12px;
}
.eye-container {
  position: relative;
  height: 400px;
  background: var(--bg-color);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 4px;
}
.eye {
  position: relative;
  width: 225px;
  height: 225px;
  background: #fff;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.eye-pupils {
  position: absolute;
  left: var(--eye-left);
  top: var(--eye-top);
  width: 64px;
  height: 64px;
  background: #000;
  border-radius: 50%;
  box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
  transform: translate(-50%, -50%);
}
.eye-box {
  position: relative;
  width: 80%;
  height: 80%;
}
.info {
  padding: 12px 0;
}

js部分

js 复制代码
const eye1 = document.querySelectorAll('.eye-pupils')[0]
const eye2 = document.querySelectorAll('.eye-pupils')[1]
let clientHeight = document.documentElement.clientHeight
let clientWidth = document.documentElement.clientWidth
window.addEventListener('mousemove', (e) => {
  requestAnimationFrame(() => {
    const { x, y } = e
    let left = (x / clientWidth) * 100
    let top = (y / clientHeight) * 100
    document.body.style.setProperty('--eye-left', `${left}%`)
    document.body.style.setProperty('--eye-top', `${top}%`)
  })
})
window.addEventListener('resize', () => {
  clientHeight = document.documentElement.clientHeight
  clientWidth = document.documentElement.clientWidth
})
相关推荐
H_Lisa2 分钟前
我用 Express 写了个 MCP,Claude 直接调用我的 API 了
前端
IT_陈寒9 分钟前
React的useEffect依赖数组把我坑惨了
前端·人工智能·后端
兰亭妙微UI设计公司1 小时前
兰亭妙微ui设计公司分享:B端组件命名如何支持团队协作
前端·javascript·vue.js
云和数据.ChenGuang2 小时前
光哥说Python 异常深度解析:从异常模型到工程化实践
java·前端·人工智能·python·langchain
小大宇2 小时前
Vue知识点-ElementPlus-03提示框+询问+通知
前端·javascript·vue.js
前端技术官3 小时前
前端的技术判断力是怎么练出来的?
javascript·web前端·localstorage·debounce·弱网处理
步行cgn3 小时前
Axios 请求成功但页面不显示:两个前端错误的分析与修正
前端
时间的情敌3 小时前
WebGIS + OpenLayers + GeoServer + PostGIS #量算 #点聚合
前端·geoserver·openlayers
不可能片场4 小时前
Electron 发布 cookie 库先查明文再写解密
前端·electron
郭小李4 小时前
springmvc 拦截器
java·开发语言·前端