{{template "header" .}} <meta name="keywords" content="码农随笔,个人随笔,博客,个人博客,个人笔记,技术博客,免费云笔记,云笔记,随笔,IT博客,谷歌地图,码农笔录,aiprose"> <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r128/three.min.js"></script> <title>登录 - 码农随笔</title> <style> .login-form { background: #55555555; padding: 18px; border-radius: 8px; position: fixed; left: 25%; top: 20%; width: 350px; margin: auto; } </style> </head> <body> <div class="root-container"> {{template "nav" .}} <div class="login-root"> <script type="x-shader/x-vertex" id="vertexshader"> attribute float scale; void main() { vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); gl_PointSize = scale * ( 300.0 / - mvPosition.z ); gl_Position = projectionMatrix * mvPosition; } </script> <script type="x-shader/x-fragment" id="fragmentshader"> uniform vec3 color; void main() { if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard; gl_FragColor = vec4( color, 1.0 ); } </script> <div id="threeContainer" class="threeContainer" ref="threeContainer"></div> <div class="login-form" :style="mstyle"> <el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="0px" class="loginForm"> <el-form-item prop="username"> <el-input v-model="loginForm.username" placeholder="请输入用户名"> <i slot="prefix" class="el-input__icon el-icon-user-solid"></i> </el-input> </el-form-item> <el-form-item prop="userpwd"> <el-input type="password" v-model="loginForm.userpwd" placeholder="请输入密码" show-password> <i slot="prefix" class="el-input__icon el-icon-user-solid"></i> </el-input> </el-form-item> <el-form-item prop="captcha"> <div style="display: flex"> <el-input v-model="loginForm.captcha" placeholder="请输入验证码"> <i slot="prefix" class="el-input__icon el-icon-user-solid"></i> </el-input> <img :src="captcha" width="150px" @click="getCaptcha"/> </div> </el-form-item> <div> <el-button type="primary" @click="loginHandler" :loading="loading" style="width: 48%">登陆</el-button> <el-button type="primary" @click="registHandler" :loading="loading" style="width: 48%">注册 </el-button> </div> </el-form> </div> </div> </div> </body> <script> var windowHalfX = 0 var windowHalfY = 0 var camera = null var renderer = null var scene = null var count = 0 var mouseX = 145 var mouseY = -322 var particles = null var AMOUNTX = 50 var AMOUNTY = 50 var app = new Vue({ el: ".root-container", delimiters: ['${', '}'], data: { captcha: '', loading: false, loginForm: { username: '', userpwd: '', captchaId: '' }, rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' }, { min: 5, message: '长度最少5个字符', trigger: 'blur' } ], userpwd: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 6, message: '长度最少6个字符', trigger: 'blur' } ], captcha: [ { required: true, message: '请输入验证码', trigger: 'blur' } ] }, mstyle: { left: window.innerWidth / 2 - 175 + 'px' } }, created() { this.getCaptcha() }, mounted() { const SEPARATION = 100 windowHalfX = window.innerWidth / 2 windowHalfY = window.innerHeight / 2 const container = this.$refs.threeContainer camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000) camera.position.z = 1000 scene = new THREE.Scene() const numParticles = AMOUNTX * AMOUNTY const positions = new Float32Array(numParticles * 3) const scales = new Float32Array(numParticles) let i = 0; let j = 0 for (let ix = 0; ix < AMOUNTX; ix++) { for (let iy = 0; iy < AMOUNTY; iy++) { positions[i] = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2) // x positions[i + 1] = 0 // y positions[i + 2] = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2) // z scales[j] = 1 i += 3 j++ } } const geometry = new THREE.BufferGeometry() geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)) geometry.setAttribute('scale', new THREE.BufferAttribute(scales, 1)) const material = new THREE.ShaderMaterial({ uniforms: { color: {value: new THREE.Color(0.0, 1.0, 1.0, 1.0)} }, vertexShader: document.getElementById('vertexshader').textContent, fragmentShader: document.getElementById('fragmentshader').textContent }) particles = new THREE.Points(geometry, material) scene.add(particles) renderer = new THREE.WebGLRenderer({antialias: true}) renderer.setPixelRatio(window.devicePixelRatio) renderer.setSize(window.innerWidth, window.innerHeight) container.appendChild(renderer.domElement) // containerParent.append(container) container.style.touchAction = 'none' container.addEventListener('pointermove', this.onPointerMove) window.addEventListener('resize', this.onWindowResize) this.animate() }, methods: { animate() { requestAnimationFrame(this.animate) this.render() }, getCaptcha() { const _this = this $.get('/api/authc/captcha', function (resp) { if (resp.Status === 0) { _this.loginForm.captchaId = resp.Data.captchaId _this.captcha = resp.Data.img } }, 'json') }, render() { camera.position.x += (mouseX - camera.position.x) * 0.05 camera.position.y += (-mouseY - camera.position.y) * 0.05 camera.lookAt(scene.position) const positions = particles.geometry.attributes.position.array const scales = particles.geometry.attributes.scale.array let i = 0; let j = 0 for (let ix = 0; ix < AMOUNTX; ix++) { for (let iy = 0; iy < AMOUNTY; iy++) { positions[i + 1] = (Math.sin((ix + count) * 0.3) * 50) + (Math.sin((iy + count) * 0.5) * 50) scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 5 + (Math.sin((iy + count) * 0.5) + 1) * 5 i += 3 j++ } } particles.geometry.attributes.position.needsUpdate = true particles.geometry.attributes.scale.needsUpdate = true renderer.render(scene, camera) count += 0.08 }, onWindowResize() { this.mstyle.left = window.innerWidth / 2 - 175 + 'px' windowHalfX = window.innerWidth / 2 windowHalfY = window.innerHeight / 2 camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth, window.innerHeight) }, onPointerMove(event) { if (event.isPrimary === false) return mouseX = event.clientX - windowHalfX // mouseY = event.clientY - windowHalfY }, login() { var _this = this if (this.user.username.trim().length < 4) { this.$message.warning('用户名最低4位'); return } if (this.user.userpwd.trim().length < 6) { this.$message.warning('密码最低6位'); return } $.post('/api/login', this.user, function (data) { if (data.Status == 1) { _this.$message.warning(data.Msg); } else { _this.$message.success("登录成功"); window.location.href = "/" } }, 'json') }, loginHandler() { const _this = this this.loading = true this.$refs.loginForm.validate(valid => { if (valid) { $.post('/api/login', this.loginForm, function (data) { this.loading = false if (data.Status == 1) { _this.getCaptcha() _this.message.warning(data.Msg); } else { _this.$message.success("登录成功"); window.location.href = "/" } }, 'json') } else { this.loading = false } }) }, registHandler() { const _this = this this.loading = true this.$refs.loginForm.validate(valid => { if (valid) { $.post('/api/regist', this.loginForm, function (data) { this.loading = false _this.getCaptcha() if (data.Status == 1) { _this.$message.warning(data.Msg); } else { _this.$message.success("注册成功,请登陆"); } }, 'json') } else { this.loading = false } }) } } }) </script> <script type="text/javascript" src="/static/js/seo.js"></script> </html>