前段时间,咱们摸金群的小伙伴发了一个网站的首页很有意思,鼠标移动,眼睛会跟着移动,并且还会眨眼,很久不动了,眼睛还会闭起来,链接在这:坏打印机。大家可以在线感受下。我也录了个gif图片,是不是有点意思?
今天我们一步一步把它给实现了。
获取底图资源
从官网看,这整个底图就是一个svg。我们把它copy到我们自己的html中,并设置下body背景色为黑色:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
background-color: #000;
}
</style>
</head>
<body>
<svg data-v-5d3d8b0b="" id="logo_svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 734 554.58">
<g data-v-5d3d8b0b="" id="图层_2" data-name="图层 2">
<g data-v-5d3d8b0b="" id="图层_1-2" data-name="图层 1" fill="#fff">
<path data-v-5d3d8b0b=""
d="M711.91,360,520.69,81a186.32,186.32,0,0,0-307.38,0L22.09,360c-26.55,38.74-29.33,86.68-7.44,128.23s63,66.36,110,66.36H609.37c47,0,88.08-24.81,110-66.36S738.46,398.73,711.91,360ZM367,329.86c74.92,0,135.88,43,135.88,95.83s-61,95.82-135.88,95.82-135.88-43-135.88-95.82S292.08,329.86,367,329.86Zm176,95.83c0-32.79-14.79-64-41.81-88.39a57.24,57.24,0,1,0-96.07-44.4,233.21,233.21,0,0,0-76.22,0,57.24,57.24,0,1,0-96.07,44.4c-27,24.43-41.81,55.6-41.81,88.39,0,33.2,14.88,64.27,42.24,88.78H124.63c-31.82,0-59.66-16.81-74.49-45s-13-60.61,5-86.85l191.22-279C274.08,63.27,318,40.11,367,40.11s92.92,23.16,120.6,63.55l191.22,279c18,26.24,19.87,58.71,5,86.85s-42.67,45-74.49,45H500.76C528.11,490,543,458.89,543,425.69Z"
class="cls-1"></path>
</g>
<g data-v-5d3d8b0b="" id="图层_1-2" data-name="图层 1" fill="#fff"
transform="translate(13.60081135328548, -1.3109917530108988)">
<path data-v-5d3d8b0b=""
d="M349.43,410.21a21.3,21.3,0,0,0,35.14,0l23.19-33.83a13.79,13.79,0,0,0-11.37-21.58H337.61a13.79,13.79,0,0,0-11.37,21.58Z"
class="cls-1"></path>
</g>
<circle data-v-5d3d8b0b="" r="24" fill="black"
transform="translate(297.4478007306761, 284.46662534712266) scale(1, 0.9961503835103371)"></circle>
<circle data-v-5d3d8b0b="" cx="270" cy="290" r="24" fill="rgba(0, 0, 0, 0)"></circle>
<circle data-v-5d3d8b0b="" r="24" fill="black"
transform="translate(488.95544468246584, 282.42345712276835) scale(1, 0.9961503835103371)"></circle>
<circle data-v-5d3d8b0b="" cx="462" cy="290" r="24" fill="rgba(0, 0, 0, 0)"></circle>
</g>
</svg>
</body>
</html>
布局排版
我们让这个svg置于浏览器中心,并设置宽高:
<style>
html,body{
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
body {
background-color: #000;
display: flex;
align-items: center;
justify-content: center;
}
#logo_svg {
width: 600px;
height: 453px;
}
</style>
ok,前两步都是准备工作,接下来要开始真正秀操作了!
操作svg元素
我们先把svg里面中文命名的id改成英文,方便我们获取:
小试牛刀
我们先拿鼻子来试试水吧,看下能不能改变它的位置,让它动起来。我们先拿到它的元素:
<script>
const nose = document.getElementById('nose');
console.log(nose);
</script>
看这后面跟着一串数字没,原网站用的是transform属性来改变位置,我们来试验一下,我们每隔0.2秒就改变一下鼻子的位置:
const nose = document.getElementById('nose');
setInterval(() => {
let x = Math.random() * 50;
let y = Math.random() * 50;
nose.setAttribute('transform', `translate(${x}, ${y})`);
}, 200);
哈哈哈,有意思,后面只需根据鼠标移动改变鼻子的位置即可。咱们后面再说。我们再来看看眼睛部分:
可以看到我圈起来的部分,提供了一个圆心位置,猜测是为了定位眼睛可转动的范围,这边它的填充色是透明的,所以为了简化实现,咱们可以定义两个变量,保存这两个圆心的位置,这两个circle咱们就可以删了
删完后,效果没变。我们获取2个眼睛就可以这么写:
const eyes = document.querySelectorAll('circle');
console.log(eyes);
用刚刚的方法,试着改变眼睛的位置:
const eyes = document.querySelectorAll('circle');
setInterval(() => {
let x = Math.random() * 20 * Math.pow(-1, Math.floor(Math.random()*2)) + 270;
let y = Math.random() * 20 * Math.pow(-1, Math.floor(Math.random()*2)) + 290;
eyes[0].setAttribute('transform', `translate(${x}, ${y})`);
eyes[1].setAttribute('transform', `translate(${x + 462 - 270}, ${y})`);
}, 200)
哈哈哈,笑死了,真的魔性~ ok,现在我们试着用鼠标来控制眼睛鼻子的位置
鼠标控制
document.body.addEventListener('mousemove', (e) => {
// 获取鼠标当前位置
let x = e.clientX;
let y = e.clientY;
// 计算鼠标位置距离眼睛的长度值
let ex = x - (window.innerWidth - 600) / 2 - 220;
let ey = y - (window.innerHeight - 453) / 2 - 240;
// 根据三角函数计算出眼睛和鼻子的位置
let angle = ex / ey;
let sy = ey > 0 ? Math.cos(Math.atan(angle)) * 20 : -Math.cos(Math.atan(angle)) * 20;
let sx = ey > 0 ? Math.sin(Math.atan(angle)) * 20 : -Math.sin(Math.atan(angle)) * 20;
eyes[0].setAttribute('transform', `translate(${sx + 270}, ${sy + 290})`);
eyes[1].setAttribute('transform', `translate(${sx + 462}, ${sy + 290})`);
// 鼻子幅度小一点
nose.setAttribute('transform', `translate(${sx / 5}, ${sy / 5})`);
})
哎呀,这三角函数整了我半天啊,不知道对不对。不过效果好像是这么回事了哈哈哈。
码上掘金
往期作品
# 一个30+大龄前端的2022年中总结(还贷,还情,还我金铲铲)
# 我用PIXI + GSAP导了一出好戏《刹车》 | 猿创营
这些都很不错哟,喜欢的可以丢个赞呀,感谢感谢!最后祝大家工作爱情双丰收~
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。