欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > html实现手势密码

html实现手势密码

2025/4/3 8:15:12 来源:https://blog.csdn.net/weixin_68658847/article/details/146912817  浏览:    关键词:html实现手势密码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>手势密码</title><style>body {font-family: Arial, sans-serif;background-color: #e2e2e2;margin: 0;padding: 0;}.draw-container {width: 100%;height: 100vh;display: flex;flex-direction: column;align-items: center;justify-content: flex-start;}.message-tip {height: 8vh;background: #f2f2f2;text-align: center;line-height: 8vh;color: #0087ce;font-size: 16px;width: 100%;}.hackout-draw-lock-wrapper {width: 100%;height: 80vh;display: flex;justify-content: center;align-items: center;}canvas {border: 1px solid #ccc;}.popup-wrapper {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.5);display: flex;justify-content: center;align-items: center;z-index: 1000;display: none;}.pop-div {width: 300px;background: #ccc;padding: 20px;border-radius: 10px;text-align: center;}.title-content {display: flex;justify-content: space-between;align-items: center;background: #0087ce;color: #fff;padding: 10px;border-radius: 5px 5px 0 0;}.btns {margin-top: 20px;}.btn {display: block;margin: 10px auto;padding: 10px;background: #fff;color: #0087ce;border: 1px solid #0087ce;border-radius: 5px;cursor: pointer;}</style>
</head><body><div class="draw-container"><div class="message-tip" id="message-tip">绘制您的解锁图案</div><div class="hackout-draw-lock-wrapper"><canvas id="firstCanvas" width="350" height="350"></canvas></div></div><div class="popup-wrapper" id="popup"><div class="pop-div"><div class="title-content"><span>请选择</span><span class="close" onclick="closePopup()">×</span></div><div class="btns"><div class="btn" onclick="resetHandLock()">重绘解锁图案</div><div class="btn" onclick="closeHandLock()">关闭解锁图案</div></div></div></div><script>const canvas = document.getElementById('firstCanvas');const context = canvas.getContext('2d');const messageTip = document.getElementById('message-tip');const popup = document.getElementById('popup');const width = canvas.width;const height = canvas.height;const background = 'rgba(0,0,0,0)';const lineColor = '#0087ce';const errorColor = '#f00';const lineBackground = 'rgba(0, 135, 206, 0.5)'; // 蓝色外圆的透明度const errorBackground = 'rgba(255, 0, 0, 0.5)'; // 红色外圆的透明度const circleWidth = 34;const rowPont = 3;const colPont = 3;let initCircleCoordinate = [];let selectedCoordinate = [];let candidateCoordinate = [];let isActive = false;let circleR = 0;let userGesture = ''; // 已设置的用户手势密码let firstGesture = ""; // 第一次手势let pass = ''; // 手势let lineError = false; // 是否显示错误circleR = Math.min(width, height) * 28 / 375;initCanvas();function initCanvas() {initCircleCoordinate = getCircleCoordinate();candidateCoordinate = initCircleCoordinate;selectedCoordinate = [];lineError = false; // 重置错误状态draw();}function touchStart(event) {event.preventDefault();initCanvas();const po = getPosition(event);if (!po) return;for (let i = 0; i < candidateCoordinate.length; i++) {if (collisionDetection(po, candidateCoordinate[i])) {isActive = true;selectedCoordinate.push(candidateCoordinate[i]);candidateCoordinate.splice(i, 1);draw();break;}}}function touchEnd(event) {if (isActive) {isActive = false;draw();const gesture = getPassword();console.log('gesture', gesture);if (gesture.length < 4) {lineError = true;messageTip.textContent = '请至少连接4个点';return;}const gestureStr = gesture.join('');if (!userGesture) {if (firstGesture === "") {firstGesture = gestureStr;messageTip.textContent = '再次绘制您的解锁图案';initCanvas();} else if (firstGesture !== gestureStr) {messageTip.textContent = '两次绘制不一致!';lineError = true;drawError(); // 绘制错误提示setTimeout(() => {lineError = false;initCanvas();}, 1000); // 1秒后恢复} else {userGesture = gestureStr;messageTip.textContent = '您的新解锁图案';lineError = false;popup.style.display = 'flex';}} else {pass = gestureStr;if (pass !== userGesture) {messageTip.textContent = '解锁图案绘制错误!';lineError = true;drawError(); // 绘制错误提示setTimeout(() => {lineError = false;initCanvas();}, 1000); // 1秒后恢复return;}messageTip.textContent = '解锁图案验证成功~';lineError = false;}}}function touchMove(event) {if (isActive) {const po = getPosition(event);if (!po) return;updateCanvas(po);}}function updateCanvas(po) {draw();const last = selectedCoordinate[selectedCoordinate.length - 1];context.beginPath();context.moveTo(po.x, po.y);context.lineTo(last.x, last.y);context.closePath();context.stroke();for (let i = 0; i < candidateCoordinate.length; i++) {if (collisionDetection(po, candidateCoordinate[i])) {selectedCoordinate.push(candidateCoordinate[i]);candidateCoordinate.splice(i, 1);break;}}}function collisionDetection(a, b) {const rX = Math.abs(a.x - b.x);const rY = Math.abs(a.y - b.y);return rX * rX + rY * rY < circleR * circleR;}function getPosition(event) {const rect = canvas.getBoundingClientRect();if (event.touches) {return {x: event.touches[0].clientX - rect.left,y: event.touches[0].clientY - rect.top};} else {return {x: event.clientX - rect.left,y: event.clientY - rect.top};}}function draw() {onDefaultDraw();}function onDefaultDraw() {context.clearRect(0, 0, width, height);context.fillStyle = background;context.fillRect(0, 0, width, height);context.lineWidth = 1;context.strokeStyle = lineColor;context.beginPath();for (let i = 0; i < initCircleCoordinate.length; i++) {context.moveTo(initCircleCoordinate[i].x + circleR, initCircleCoordinate[i].y);context.arc(initCircleCoordinate[i].x, initCircleCoordinate[i].y, circleR, 0, Math.PI * 2, true);}context.stroke();context.closePath();context.strokeStyle = lineColor;context.beginPath();for (let i = 0; i < selectedCoordinate.length; i++) {context.lineTo(selectedCoordinate[i].x, selectedCoordinate[i].y);}context.stroke();context.closePath();context.fillStyle = lineBackground;context.beginPath();for (let i = 0; i < selectedCoordinate.length; i++) {context.moveTo(selectedCoordinate[i].x + circleR / 2, selectedCoordinate[i].y);context.arc(selectedCoordinate[i].x, selectedCoordinate[i].y, circleR, 0, Math.PI * 2, true);}context.fill();context.closePath();context.fillStyle = lineColor;context.beginPath();for (let i = 0; i < selectedCoordinate.length; i++) {context.moveTo(selectedCoordinate[i].x + circleR / 2, selectedCoordinate[i].y);context.arc(selectedCoordinate[i].x, selectedCoordinate[i].y, circleR * 0.6, 0, Math.PI * 2, true);}context.fill();context.closePath();}function drawError() {context.clearRect(0, 0, width, height);context.fillStyle = background;context.fillRect(0, 0, width, height);context.lineWidth = 1;context.strokeStyle = errorColor;context.beginPath();for (let i = 0; i < initCircleCoordinate.length; i++) {context.moveTo(initCircleCoordinate[i].x + circleR, initCircleCoordinate[i].y);context.arc(initCircleCoordinate[i].x, initCircleCoordinate[i].y, circleR, 0, Math.PI * 2, true);}context.stroke();context.closePath();context.strokeStyle = errorColor;context.beginPath();for (let i = 0; i < selectedCoordinate.length; i++) {context.lineTo(selectedCoordinate[i].x, selectedCoordinate[i].y);}context.stroke();context.closePath();context.fillStyle = errorBackground;context.beginPath();for (let i = 0; i < selectedCoordinate.length; i++) {context.moveTo(selectedCoordinate[i].x + circleR / 2, selectedCoordinate[i].y);context.arc(selectedCoordinate[i].x, selectedCoordinate[i].y, circleR, 0, Math.PI * 2, true);}context.fill();context.closePath();context.fillStyle = errorColor;context.beginPath();for (let i = 0; i < selectedCoordinate.length; i++) {context.moveTo(selectedCoordinate[i].x + circleR / 2, selectedCoordinate[i].y);context.arc(selectedCoordinate[i].x, selectedCoordinate[i].y, circleR * 0.6, 0, Math.PI * 2, true);}context.fill();context.closePath();}function getCircleCoordinate() {const offsetx = (width - rowPont * circleR * 2) / (rowPont + 1);const offsety = (height - colPont * circleR * 2) / (colPont + 1);const circleCoordinate = [];for (let col = 0; col < colPont; col++) {for (let row = 0; row < rowPont; row++) {circleCoordinate.push({x: offsetx * (row + 1) + circleR * (2 * row + 1),y: offsety * (col + 1) + circleR * (2 * col + 1),key: 3 * col + row + 1});}}return circleCoordinate;}function getPassword() {return selectedCoordinate.map(item => item.key);}function closePopup() {popup.style.display = 'none';}function resetHandLock() {userGesture = "";firstGesture = "";messageTip.textContent = '设置您的解锁图案';closePopup();initCanvas(); // 重置画布}function closeHandLock() {userGesture = "";closePopup();initCanvas(); // 重置画布}// 根据设备类型绑定事件var userAgent = navigator.userAgent;var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);var deviceType = isMobile ? "移动端" : "PC端";if (deviceType == "移动端") {console.log('移动端');canvas.addEventListener('touchstart', touchStart);canvas.addEventListener('touchmove', touchMove);canvas.addEventListener('touchend', touchEnd);} else {console.log('PC端');canvas.addEventListener('mousedown', touchStart);canvas.addEventListener('mousemove', touchMove);canvas.addEventListener('mouseup', touchEnd);}</script>
</body></html>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词