效果
背景
在登录的时候,我们都会做账号密码不可为空的验证,如何做出一个会躲避鼠标指针的登录按钮呢。废话不多说,3、2、1,上代码~
代码
<!DOCTYPE html>
<html lang="en" style="overflow: hidden;">
<head>
<title>登录测试</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-plus/2.3.3/index.css" rel="stylesheet">
<script src="https://unpkg.com/vue@3"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/element-plus/2.3.3/index.full.js"></script>
<style>
body {
background-color: rgb(132, 141, 156);
user-select: none;
}
#form {
width: 300px;
perspective: 400px;
position: absolute;
top: 300px;
left: 50%;
margin-left: -150px;
padding: 20px;
box-shadow: var(--el-box-shadow-light);
border-radius: 5px;
border: 1px solid var(--el-card-border-color);
background-color: rgb(230, 240, 250);
}
.remember-me-wrapper {
float: right;
margin-bottom: 18px;
}
.remember-me-wrapper .el-checkbox {
z-index: 0;
}
#button {
width: 100%;
transition: all 0.1s ease;
transform: translate(0px, 0px) rotateX(0deg) rotateY(0deg);
box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.15)
}
</style>
</head>
<body>
<div id="app">
<el-form id="form" :model="loginForm" :rules="loginRules" label-width="60">
<el-form-item label="账号" prop="username">
<el-input v-model="loginForm.username" clearable />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="loginForm.password" clearable type="password" />
</el-form-item>
<div class="remember-me-wrapper">
<el-checkbox v-model="loginForm.rememberMe" label="记住我" class="rememberMe" />
</div>
<el-button id="button" type="primary" @click="login()">登录</el-button>
</el-form>
</div>
<script type="text/javascript">
const { createApp, reactive, ref } = Vue
const app = createApp({
setup() {
const loginForm = reactive({
username: '',
password: '',
rememberMe: false
})
const loginRules = reactive({
username: [
{ required: true, message: '不可为空', trigger: 'blur' }
],
password: [
{ required: true, message: '不可为空', trigger: 'blur' }
]
})
const distanceBetween = (p1x, p1y, p2x, p2y) => {
const dx = p1x - p2x
const dy = p1y - p2y
return Math.sqrt(dx * dx + dy * dy)
}
document.addEventListener('mousemove', (event) => {
const button = document.getElementById('button')
const form = document.getElementById('form')
if (loginForm.username && loginForm.password) {
button.style.transform = `translate(0px, 0px) rotateX(0deg) rotateY(0deg)`
button.style.boxShadow = `0px 0px 0px rgba(0, 0, 0, 0.15)`
button.style.pointerEvents = 'auto'
return
}
const bx = form.offsetLeft + button.offsetLeft + button.offsetWidth / 2
const by = form.offsetTop + button.offsetTop + button.offsetHeight / 2
const dist = distanceBetween(event.clientX, event.clientY, bx, by) * 2
const angle = Math.atan2(event.clientY - by, event.clientX - bx)
// 椭圆半径公式
const radius = Math.sqrt(Math.pow(button.offsetWidth + 20, 2) * Math.pow(Math.cos(angle), 2) + Math.pow(button.offsetHeight + 20, 2) * Math.pow(Math.sin(angle), 2))
const ox = -1 * Math.cos(angle) * (Math.max((radius - dist) / 2, 0))
const oy = -1 * Math.sin(angle) * (Math.max((radius - dist) / 2, 0))
const rx = oy / 2
const ry = -ox / 2
button.style.transform = `translate(${ox}px, ${oy}px) rotateX(${rx}deg) rotateY(${ry}deg)`
button.style.boxShadow = `0px ${Math.abs(oy)}px ${Math.abs(oy) / radius * 40}px rgba(0, 0, 0, 0.15)`
button.style.pointerEvents = 'none'
})
const login = () => {
if (loginForm.username && loginForm.password) {
ElementPlus.ElMessage({
message: '登录成功',
type: 'success',
})
}
}
return {
loginForm,
loginRules,
login
}
}
})
app.use(ElementPlus).mount("#app")
</script>
</body>
</html>