实现效果:html源码来自b站up主:【CSS+JS】甲方:啊?没叫你做那么超前啊_哔哩哔哩_bilibili

本人仅实现了将html格式改为vue3

html版:

对于前端连入门可能都没摸到,学了半天也就改成vue3了,对于输入密码时会显示两个查看密码的问题还是没头绪,希望有大佬会的话可以讲一下。

<!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>山羊の前端小窝</title>
    <style>
        * {
            box-sizing: border-box;
            transition: .2s;
        }

        :root {
            --bgColor: white;
            --border: black;
            --inputColor: black;
            --outlineColor: rgb(60, 115, 235);
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            overflow: hidden;
            background: var(--bgColor);
        }

        body.show-password {
            --bgColor: rgba(0, 0, 0, 0.9);
            --inputColor: white;
            --border: rgb(255, 255, 255);
        }

        .shell {
            width: 100%;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            background-image: url(./img/1.png);
            background-size: cover;
        }

        form {
            transform: translate3d(0, 0, 0);
            padding: 50px;
            border: 20px solid var(--border);
            border-radius: 10px;
            box-shadow: 10px 10px 10px #00000065;
        }

        form > * + * {
            margin-top: 15px;
        }

        .form-item > * + * {
            margin-top: 0.5rem;
        }

        h2,
        label,
        input,
        button {
            font-size: 2rem;
            font-family: '优设标题黑';
            color: var(--inputColor);
        }

        h2 {
            font-size: 4rem;
            margin: 0;
        }

        label:focus,
        input:focus,
        button:focus {
            outline-offset: 2px;
        }

        label::-moz-focus-inner,
        input::-moz-focus-inner,
        button::-moz-focus-inner {
            border: none;
        }

        label[id=password],
        input[id=password],
        button[id=password] {
            color: black;
        }

        button {
            border: none;
        }

        [id=submit] {
            cursor: pointer;
            width: 100%;
            margin: 20px 0 0 2px;
            padding: 0.75rem 1.25rem;
            color: var(--bgColor);
            background-color: var(--inputColor);
            box-shadow: 4px 4px 0 rgba(30, 144, 255, 0.2);
        }

        [id=submit]:active {
            transform: translateY(1px);
        }

        .input-wrapper {
            position: relative;
        }

        input {
            padding: 0.75rem 4rem 0.75rem 0.75rem;
            width: 100%;
            border: 2px solid transparent;
            border-radius: 0;
            /* 设置背景颜色为透明 */
            background-color: transparent;
            box-shadow: inset 0 0 0 2px black,
            inset 6px 6px 0 rgba(30, 144, 255, 0.2),
            3px 3px 0 rgba(30, 144, 255, 0.2);
            -webkit-appearance: none;
        }

        input:focus {
            outline-offset: 1px;
        }

        .show-password input {
            box-shadow: inset 0 0 0 2px black;
            border: 2px dashed white;
        }

        .show-password input:focus {
            outline: none;
            border-color: rgb(255, 255, 145);
        }

        /* 设置眼睛按钮样式 */
        [id=eyeball] {
            --size: 1.25rem;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            outline: none;
            position: absolute;
            top: 50%;
            right: 0.75rem;
            border: none;
            background-color: transparent;
            transform: translateY(-50%);
        }

        [id=eyeball]:active {
            transform: translateY(calc(-50% + 1px));
        }

        .eye {
            width: var(--size);
            height: var(--size);
            border: 2px solid var(--inputColor);
            border-radius: calc(var(--size) / 1.5) 0;
            transform: rotate(45deg);
        }

        .eye:before,
        .eye:after {
            content: "";
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            margin: auto;
            border-radius: 100%;
        }

        .eye:before {
            width: 35%;
            height: 35%;
            background-color: var(--inputColor);
        }

        .eye:after {
            width: 65%;
            height: 65%;
            border: 2px solid var(--inputColor);
            border-radius: 100%;
        }

        /* 设置光束样式 */
        [id=beam] {
            position: absolute;
            top: 50%;
            right: 1.75rem;
            clip-path: polygon(100% 50%, 100% 50%, 0 0, 0 100%);
            width: 100vw;
            height: 25vw;
            z-index: 1;
            mix-blend-mode: multiply;
            transition: transform 200ms ease-out;
            transform-origin: 100% 50%;
            transform: translateY(-50%) rotate(var(--beamDegrees, 0));
            pointer-events: none;
        }

        .show-password [id=beam] {
            background: rgb(255, 255, 145);
        }
    </style>
</head>

<body>
<div class="shell">
    <form>
        <h2>LOGIN</h2>
        <div class="form-item">
            <label for="username">Username</label>
            <div class="input-wrapper">
                <input type="text" id="username"/>
            </div>
        </div>
        <div class="form-item">
            <label for="password">Password</label>
            <div class="input-wrapper">
                <input type="password" id="password"/>
                <button type="button" id="eyeball">
                    <div class="eye"></div>
                </button>
                <div id="beam"></div>
            </div>
        </div>
        <button id="submit">Sign in</button>
    </form>
</div>
<script>
    const root = document.documentElement;
    const eye = document.querySelector('#eyeball');
    const beam = document.querySelector('#beam');
    const passwordInput = document.querySelector('#password');
    root.addEventListener('mousemove', (e) => {
        let rect = beam.getBoundingClientRect();
        let mouseX = rect.right + (rect.width / 2);
        let mouseY = rect.top + (rect.height / 2);
        let rad = Math.atan2(mouseX - e.pageX, mouseY - e.pageY);
        let degrees = (rad * (20 / Math.PI) * -1) - 350;
        root.style.setProperty('--beamDegrees', `${degrees}deg`);
    });
    eye.addEventListener('click', e => {
        e.preventDefault();
        document.body.classList.toggle('show-password');
        passwordInput.type = passwordInput.type === 'password' ? 'text' : 'password';
        //passwordInput.focus();
    });
</script>
</body>

</html>

vue3版本:

不是很会前端,改为vue3后部分效果消失,自己试着改了改,可以直接在handleLogin中处理自己的提交方法。

会提示beam元素可能为空,但不影响实际使用。

<template>
  <div ref="bigBox" class="bigBox" :class="{ showPassword: isshowPassword }">
    <div class="shell">
      <form @submit.prevent="handleLogin">
        <h2>LOGIN</h2>
        <div class="form-item">
          <label for="username">Username</label>
          <div class="input-wrapper">
            <input
              type="text"
              id="userAccount"
              v-model="Loginform.userAccount"
              autocomplete="off"
              autocorrect="off"
              autocapitalize="off"
              spellcheck="false"
              data-lpignore="true"
            />
          </div>
        </div>
        <div class="form-item">
          <label for="userPassword">Password</label>
          <div class="input-wrapper">
            <input
              :type="showPasswordType"
              id="password"
              ref="password"
              v-model="Loginform.userPassword"
              autocomplete="off"
              autocorrect="off"
              autocapitalize="off"
              spellcheck="false"
              data-lpignore="true"
            />
            <button type="button" id="eyeball" @click="eyeball">
              <div class="eye"></div>
            </button>
            <div id="beam"></div>
          </div>
        </div>
        <button id="submit">Login in</button>
      </form>
    </div>
  </div>
</template>
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from "vue";
import { UserControllerService, UserLoginRequest } from "../../../../generated";
import { useRouter } from "vue-router";
import { useStore } from "vuex";

const router = useRouter();
const store = useStore();
// 创建响应式表单数据
const Loginform = reactive({
  userAccount: "",
  userPassword: "",
} as UserLoginRequest);
// 定义登录处理函数
const handleLogin = async () => {
  // 弹窗显示账号密码
  alert(JSON.stringify(Loginform));  
};
/**
 * css样式
 */

const form = reactive({
  showPassword: false,
});
let passwordInput = document.querySelector("#password");
// 计算属性,根据 showPassword 的值返回 'password' 或 'text'
const showPasswordType = computed(() =>
  form.showPassword ? "text" : "password"
);

let isshowPassword = ref(false);

onMounted(() => {
  const root = ref(document.documentElement); // 获取根元素
  const beam = document.querySelector("#beam"); // 获取光束元素
  const eye = document.querySelector("#eyeball"); // 获取眼睛按钮元素
  passwordInput = document.querySelector("#password"); // 获取密码输入框元素

  // 然后使用 beam.value, eye.value, passwordInput.value 来访问 DOM 元素
  // 鼠标移动事件监听器
  root.value.addEventListener("mousemove", (e) => {
    // 获取光束的位置和鼠标位置
    let rect = beam.getBoundingClientRect(); // 获取光束元素的位置信息
    let mouseX = rect.right + rect.width / 2; // 光束的横坐标
    let mouseY = rect.top + rect.height / 2; // 光束的纵坐标
    // 计算角度
    let rad = Math.atan2(mouseX - e.pageX, mouseY - e.pageY); // 计算鼠标和光束之间的角度
    let degrees = rad * (20 / Math.PI) * -1 - 350; // 将弧度转换为角度
    // 设置根元素的样式变量
    root.value.style.setProperty("--beamDegrees", `${degrees}deg`); // 设置根元素的样式变量,控制光束的旋转角度
  });
});
//点击显示密码
const eyeball = () => {
  form.showPassword = !form.showPassword;
  if (!isshowPassword.value) {
    isshowPassword.value = true;
  } else {
    isshowPassword.value = false;
  }
};
</script>
<style scoped>
/* 设置全局样式 */
* {
  box-sizing: border-box;
  transition: 0.2s;
}

/* 设置根元素变量 */
:root {
  --bgColor: white;
  /* 设置背景颜色变量为白色 */
  --inputColor: black;
  /* 设置输入框颜色变量为黑色 */
  --outlineColor: rgb(60, 115, 235);
  /* 设置输入框边框颜色变量为RGB(60, 115, 235) */
  --border: black;
  --beamDegrees: 0deg; /* 添加默认值 */
  /* ... 其他变量定义 */
}

/* 设置body样式 */
.bigBox {
  display: flex;
  /* 设置body元素为flex布局 */
  justify-content: center;
  /* 水平居中对齐 */
  align-items: center;
  /* 垂直居中对齐 */
  height: 100vh;
  /* 设置body元素的高度为视口高度 */
  overflow: hidden;
  /* 隐藏溢出内容 */
  background: var(--bgColor, #ffffff);
  /* 设置背景颜色为变量--bgColor的值 */
}

/* 设置外层容器样式 */
.shell {
  width: 100%;
  /* 设置外层容器的宽度为100% */
  height: 100vh;
  /* 设置外层容器的高度为视口高度 */
  display: flex;
  /* 设置外层容器为flex布局 */
  align-items: center;
  /* 垂直居中对齐 */
  justify-content: center;
  /* 水平居中对齐 */
  background-image: url(../../img/1.webp);
  /* 设置背景图片为./img/1.png */
  background-size: cover;
  /* 背景图片等比例缩放铺满容器 */
}

/* 设置表单样式 */
form {
  transform: translate3d(0, 0, 0);
  /* 3D变换,无位移 */
  padding: 50px;
  /* 设置内边距为10px */
  border: 20px solid var(--border, #000000);
  border-radius: 10px;
  box-shadow: 10px 10px 10px #00000065;
}

form > * + * {
  margin-top: 15px;
  /* 设置相邻元素之间的上边距为15px */
}

.form-item > * + * {
  margin-top: 0.5rem;
  /* 设置相邻元素之间的上边距为0.5rem */
}

/* 设置label, input, button样式 */
h2,
label,
input,
button {
  font-size: 2rem;
  /* 设置字体大小为2rem */
  color: var(--inputColor, #000000);
  /* 设置字体颜色为变量--inputColor的值 */
  font-family: "优设标题黑";
}

h2 {
  font-size: 4rem;
  margin: 0;
}

label:focus,
input:focus,
button:focus {
  outline-offset: 2px;
  /* 设置聚焦时的外边距为2px */
}

label::-moz-focus-inner,
input::-moz-focus-inner,
button::-moz-focus-inner {
  border: none;
  /* 去掉Firefox浏览器的聚焦时的内边框 */
}

/* 设置密码相关样式 */
label[id="userPassword"],
input[id="userPassword"],
button[id="userPassword"] {
  color: black;
  /* 设置字体颜色为黑色 */
}

/* 设置按钮样式 */
button {
  border: none;
  /* 去掉按钮的边框 */
}

[id="submit"] {
  width: 100%;
  cursor: pointer;
  /* 设置鼠标样式为手型 */
  margin: 20px 0 0 2px;
  /* 设置外边距为20px 0 0 2px */
  padding: 0.75rem 1.25rem;
  /* 设置内边距为0.75rem 1.25rem */
  color: var(--bgColor, #ffffff);
  /* 设置字体颜色为变量--bgColor的值 */
  background-color: var(--inputColor, #000000);
  /* 设置背景颜色为变量--inputColor的值 */
  box-shadow: 4px 4px 0 rgba(30, 144, 255, 0.2);
  /* 设置阴影效果 */
}

[id="submit"]:active {
  transform: translateY(1px);
  /* 设置点击时向下位移1px */
}

/* 设置输入框包裹器样式 */
.input-wrapper {
  position: relative;
  /* 设置相对定位 */
}

/* 设置输入框样式 */
input {
  padding: 0.75rem 4rem 0.75rem 0.75rem;
  /* 设置内边距为0.75rem 4rem 0.75rem 0.75rem */
  width: 100%;
  /* 设置宽度为100% */
  border: 2px solid transparent;
  /* 设置边为2px透明 */
  border-radius: 0;
  /* 设置边框圆角为0 */
  background-color: transparent;
  /* 设置背景颜色为透明 */
  box-shadow: inset 0 0 0 2px black, inset 6px 6px 0 rgba(30, 144, 255, 0.2),
    3px 3px 0 rgba(30, 144, 255, 0.2);
  /* 设置阴影效果 */
  -webkit-appearance: none;
  /* 去掉Webkit浏览器的默认样式 */
}

/*输入密码后样式*/
input:focus {
  outline-offset: 1px;
  /* 设置聚焦时的外边距为1px */
}

/* 设置显示密码时的输入框样式 */
.showPassword input {
  box-shadow: inset 0 0 0 2px black;
  /* 设置阴影效果 */
  border: 2px dashed white;
  /* 设置边框为2px虚线白色 */
}

.showPassword input:focus {
  outline: none;
  /* 去掉聚焦时的外边框 */
  border-color: rgb(255, 255, 145);
  /* 设置边框颜色为RGB(255, 255, 145) */
}

.showPassword input[id="userPassword"] {
  type: text;
}

/* 设置眼睛按钮样式 */
[id="eyeball"] {
  --size: 1.25rem;
  /* 设置变量--size的值为1.25rem */
  display: flex;
  /* 设置为flex布局 */
  align-items: center;
  /* 垂直居中对齐 */
  justify-content: center;
  /* 水平居中对齐 */
  cursor: pointer;
  /* 设置鼠标样式为手型 */
  outline: none;
  /* 去掉聚焦时的外边框 */
  position: absolute;
  /* 设置绝对定位 */
  top: 50%;
  /* 设置顶部距离为50% */
  right: 0.75rem;
  /* 设置右侧距离为0.75rem */
  border: none;
  /* 去掉边框 */
  background-color: transparent;
  /* 设置背景颜色为透明 */
  transform: translateY(-50%);
  /* 设置向上位移50% */
}

[id="eyeball"]:active {
  transform: translateY(calc(-50% + 1px));
  /* 设置点击时向上位移50% + 1px */
}

.eye {
  width: var(--size);
  /* 设置宽度为变量--size的值 */
  height: var(--size);
  /* 设置高度为变量--size的值 */
  border: 2px solid var(--inputColor, #000000);
  /* 设置边框为2px实线,颜色为变量--inputColor的值 */
  border-radius: calc(var(--size) / 1.5) 0;
  /* 设置边框圆角为变量--size的值除以1.5,0 */
  transform: rotate(45deg);
  /* 设置旋转45度 */
}

.eye:before,
.eye:after {
  content: "";
  /* 清空内容 */
  position: absolute;
  /* 设置绝对定位 */
  top: 0;
  /* 设置顶部距离为0 */
  right: 0;
  /* 设置右侧距离为0 */
  bottom: 0;
  /* 设置底部距离为0 */
  left: 0;
  /* 设置左侧距离为0 */
  margin: auto;
  /* 设置自动外边距 */
  border-radius: 100%;
  /* 设置边框圆角为100% */
}

.eye:before {
  width: 35%;
  /* 设置宽度为35% */
  height: 35%;
  /* 设置高度为35% */
  background-color: var(--inputColor, #000000);
  /* 设置背景颜色为变量--inputColor的值 */
}

.eye:after {
  width: 65%;
  /* 设置宽度为65% */
  height: 65%;
  /* 设置高度为65% */
  border: 2px solid var(--inputColor, #000000);
  /* 设置边框为2px实线,颜色为变量--inputColor的值 */
  border-radius: 100%;
  /* 设置边框圆角为100% */
}

/* 设置光束样式 */
[id="beam"] {
  position: absolute;
  /* 设置绝对定位 */
  top: 50%;
  /* 设置顶部距离为50% */
  right: 1.75rem;
  /* 设置右侧距离为1.75rem */
  clip-path: polygon(100% 50%, 100% 50%, 0 0, 0 100%);
  /* 设置剪切路径为多边形 */
  width: 100vw;
  /* 设置宽度为100vw */
  height: 25vw;
  /* 设置高度为25vw */
  z-index: 1;
  /* 设置层级为1 */
  mix-blend-mode: multiply;
  /* 设置混合模式为multiply */
  transition: transform 200ms ease-out;
  /* 设置过渡效果为200ms的ease-out */
  transform-origin: 100% 50%;
  /* 设置变换原点为右侧50% */
  transform: translateY(-50%) rotate(var(--beamDegrees, 0));
  /* 设置向上位移50%并旋转--beamDegrees度 */
  pointer-events: none;
  /* 禁用指针事件 */
}

.showPassword [id="beam"] {
  background: rgb(255 255 145 / 73%);
  /* 设置背景颜色为RGB(255, 255, 145) */
}

/* 设置显示密码时的样式 */
.showPassword {
  --bgColor: rgba(0, 0, 0, 0.9);
  /* 设置背景颜色变量为RGBA(0, 0, 0, 0.9) */
  --inputColor: white;
  /* 设置输入框颜色变量为白色 */
  --border: rgb(255, 255, 255);
}
</style>

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部