MENU
前言
1、版本一的样式比较齐全;
2、版本二的JS逻辑和功能效果比较完善,且是别人的代码,后续会对样式进行完善。[Gitee | 哔哩哔哩];
3、两个版本各有千秋,主要学习里面的一些技巧,这里主要介绍版本一的样式技巧;
4、行为验证码一般是后端实现,而且大概率是使用第三方插件,因为涉及到的逻辑和内容比较多,前后端实现起来都比较麻烦。
版本一(html+JS+css)
案例公共样式
body{margin: 0;padding: 0;display: flex;justify-content: center;align-items: center;min-height: 100vh;}
案例一(clip-path裁剪的应用)
<style>.clip_path{width: 300px;height: 300px;background-color: #ff0000;}.clip_path:first-child{float: left;background-color: #0000ff;clip-path:inset(50px 20px 30px 40px round 10px);}</style><div><divclass="clip_path"></div><divclass="clip_path"></div></div>
案例一解析
代码块中包含两个
元素,每个元素都有类名为clip_path。此外,还有一些CSS样式被应用于这些元素。
CSS样式部分
**1、clip_path类指定了一个固定的宽度(300像素)、高度(300像素)和背景颜色(红色)的区域。
2、clip_path:first-child选择器用于选择第一个具有类名clip_path的元素,并对其应用特定样式。
2.1、float: left;
将第一个元素左浮动,使其在其右侧的元素之前显示。
2.2、background-color: #0000ff;
将第一个元素的背景颜色更改为蓝色。
2.3、clip-path: inset(50px 20px 30px 40px round 10px);
将剪切路径应用于第一个元素,剪切路径的形状是一个矩形,内边距为50px 20px 30px 40px,并且角是圆形的,半径为10px。**
HTML部分
两个元素被包含在一个外部中。
每个元素都有类名为clip_path,因此它们都受到了相同的CSS样式的影响。
综上所述,代码将显示两个相同大小的红色方块,但第一个方块的背景颜色为蓝色,并具有一种剪切路径,使其内部形成一个圆角矩形区域。
案例一效果图
案例二(clamp最大值最小值的应用)
<style>.clamp{width:clamp(300px, 50vw, 600px);height: 300px;background-color: #ff0000;}</style><divclass="clamp"></div>
案例二解析
一段简单的HTML和CSS代码段,用于创建一个具有限制宽度的元素。
**1、<style>标签用于在HTML文档中定义CSS样式。
2、.clamp是一个CSS类选择器,它用于选择具有类名为"clamp"的HTML元素。
3、width: clamp(300px, 50vw, 600px);
是一个CSS属性,它使用clamp()函数来设置元素的宽度。clamp()函数接受三个参数,分别是最小宽度、首选宽度和最大宽度。在这个例子中,元素的宽度将被限制在300像素、视窗宽度的50%和600像素之间,以保证在不同设备和屏幕尺寸下有不同的大小。
4、height: 300px;
设置元素的高度为300像素。
5、background-color: #ff0000;
设置元素的背景颜色为红色。**
是一个HTML
元素,它具有一个类名为"clamp",因此应用了上述定义的CSS样式。这个元素将具有限制宽度的特性,宽度将根据视窗宽度和定义的最小和最大宽度进行调整,以便在不同设备和屏幕尺寸下呈现出不同的大小。
案例二效果图
功能效果图
html
<divid="captcha"><divid="handle"><spanonmousedown="onmousedownFn()"mousemove="mousemoveFn()"></span></div></div>
JavaScript
const captcha = document.querySelector('#captcha');const handle = document.querySelector('#handle');const button = document.querySelector('#handle span');const oLeft = handle.getBoundingClientRect().left;const buttonWidth = button.getBoundingClientRect().width;let flag =false;functiononmousedownFn(){ flag =true;} window.addEventListener('mousemove',({ clientX })=>{if(flag){ captcha.style.setProperty('--moved',`${clientX - oLeft - buttonWidth /2}px`);}}); window.addEventListener('mouseup',({ clientX })=>{if(flag){const dis = clientX - oLeft;if(dis >=430&& dis <=450){ captcha.classList.add('passed');alert('验证通过!');}else{ captcha.style.setProperty('--moved','0px');} flag =false;}});
style
*{margin: 0;padding: 0;}body{--width: 400px;--height: 260px;--puzzle-width: 80px;--puzzle-height: 80px;--moved: 0px;background-color: #008b8b;width: 100vw;height: 100vh;display: flex;justify-content: center;align-items: center;}#captcha{width:var(--width);height:var(--height);background-image:url('https://cn.bing.com/th?id=OHR.AlmondBloom_ZH-CN9441550492_1920x1080.jpg');background-size: cover;background-position: center;position: relative;border-radius: 4px;box-shadow: 0px 2px 4px rgba(0, 0, 0, .3);}#captcha::before, #captcha::after{display: flex;position: absolute;content:'';width: inherit;height: inherit;background-image: inherit;background-size: inherit;background-position: inherit;clip-path:inset(calc((var(--height) - var(--puzzle-height)) / 2)var(--puzzle-width)calc((var(--height) - var(--puzzle-height)) / 2)calc(var(--width) - var(--puzzle-width) * 2));}#captcha::after{transform:translateX(clamp(calc(var(--width) * -1),calc(var(--width) * -1 + var(--moved)),var(--puzzle-width)));transition: .25s all ease-in-out;cursor: pointer;}#captcha:active::after{transition: none;}#captcha::before{background-color:rgba(0, 0, 0, .6);background-blend-mode: multiply;}#handle{height: 30px;width:calc(var(--width) + var(--puzzle-width) * 2);border-radius: 18px;background-color: #eeeeee;box-shadow: inset 0 0 12px rgba(0, 0, 0, .2);border: 3px solid #eeeeee;position: absolute;bottom: -50px;left:calc(var(--puzzle-width) * 2 * -1);}#handle span{width:var(--puzzle-width);height: inherit;display: block;border-radius: inherit;background-color: #fff;box-shadow: 0 0 6px rgba(0, 0, 0, .25), 0 2px 4px rgba(0, 0, 0, .3);cursor: move;transform:translateX(clamp( 0px,var(--moved),calc(var(--width) + var(--puzzle-width))));cursor: pointer;transition: .25s all ease-in-out;}#captcha:active #handle span{transition: none;}#captcha.passed::before, #captcha.passed::after, #captcha.passed #handle{opacity: 0;}
版本二(html+JS+css+canvas)
效果图
html
<divclass="container"><divid="captcha"style="position: relative;"></div><divid="msg"></div></div><scriptsrc="./indexV2.js"></script><script> captcha.init(document.getElementById('captcha'),function(){ document.getElementById('msg').innerHTML ='验证成功';setTimeout(()=>{ document.getElementById('msg').innerHTML ='';},2000);},function(){ document.getElementById('msg').innerHTML ='验证失败';setTimeout(()=>{ document.getElementById('msg').innerHTML ='';},1000);})</script>
JavaScript
(function(win){// 滑块边长let l =42,// 滑块半径 r =10,// canvas宽度 w =310,//canvas高度 h =155,PI= Math.PI;// 滑块的实际边长const ll = l + r *2;// 获取指定区间内的随机数functiongetRandomNumberByRange(start, end){return Math.round(Math.random()*(end - start)+ start);}// 创建元素functioncreateElement(tagName){return document.createElement(tagName);}// 创建画布functioncreateCanvas(width, height){const canvas =createElement('canvas'); canvas.width = width; canvas.height = height;return canvas;}// 获取随机图片functiongetRandomImg(){// 这个网站可以生成随机图片return'https://picsum.photos/300/150/?image='+getRandomNumberByRange(0,100);}// 创建图片functioncreateImg(onload){const img =createElement('img'); img.crossOrigin ='Anonymous'; img.onload = onload; img.onerror=()=>{ img.src =getRandomImg();} img.src =getRandomImg();return img;}// 添加样式functionaddClass(tag, className){ tag.classList.add(className);}// 移除样式functionremoveClass(tag, className){ tag.classList.remove(className);}// 绘制functiondraw(ctx, operation, x, y){ ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x + l /2, y); ctx.arc(x + l /2, y - r +2, r,0,2*PI); ctx.lineTo(x + l /2, y); ctx.lineTo(x + l, y); ctx.lineTo(x + l, y + l /2); ctx.arc(x + l + r -2, y + l /2, r,0,2*PI); ctx.lineTo(x + l, y + l /2); ctx.lineTo(x + l, y + l); ctx.lineTo(x, y + l); ctx.lineTo(x, y); ctx.fillStyle ='#fff'; ctx[operation](); ctx.beginPath(); ctx.arc(x, y + l /2, r,1.5*PI,0.5*PI); ctx.globalCompositeOperation ='xor'; ctx.fill();}// 求和functionsum(x, y){return x + y;}// 求平方functionsquare(x){return x * x;}// 验证码类classcaptcha{// 构造器constructor(el, success, fail){this.el = el;this.success = success;this.fail = fail;}// 初始化init(){this.initDOM();this.initImg();this.draw();this.bindEvents();}// 初始化DOMinitDOM(){const canvas =createCanvas(w, h), block = canvas.cloneNode(true), sliderContainer =createElement('div'), sliderMask =createElement('div'), slider =createElement('div'), refreshIcon =createElement('div'), sliderIcon =createElement('span'), text =createElement('span'); block.className ='block'; sliderContainer.className ='slider-container'; sliderMask.className ='slider-mask'; slider.className ='slider'; refreshIcon.className ='refresh-icon'; sliderIcon.className ='slider-icon'; text.className ='slider-text'; text.innerHTML ='向右滑动滑块填充拼图';const el =this.el; el.appendChild(canvas); el.appendChild(refreshIcon); el.appendChild(block); slider.appendChild(sliderIcon); sliderMask.appendChild(slider); sliderContainer.appendChild(sliderMask); sliderContainer.appendChild(text); el.appendChild(sliderContainer); Object.assign(this,{ canvas, block, sliderContainer, refreshIcon, slider, sliderMask, sliderIcon, text,canvasCtx: canvas.getContext('2d'),blockCtx: block.getContext('2d')});}// 初始化图像initImg(){const img =createImg(()=>{this.canvasCtx.drawImage(img,0,0, w, h);this.blockCtx.drawImage(img,0,0, w, h);const y =this.y - r *2+2;const imageData =this.blockCtx.getImageData(this.x, y, ll, ll);this.block.width = ll;this.blockCtx.putImageData(imageData,0, y);});this.img = img;}// 绘画draw(){this.x =getRandomNumberByRange(ll +10, w -(ll +10));this.y =getRandomNumberByRange(10+ r *2, h -(ll +10));draw(this.canvasCtx,'fill',this.x,this.y);draw(this.blockCtx,'clip',this.x,this.y);}// 清除clean(){this.canvasCtx.clearRect(0,0, w, h);this.blockCtx.clearRect(0,0, w, h);this.block.width = w;}// 绑定事件bindEvents(){this.el.onselectstart=()=>false;this.refreshIcon.onclick=()=>{this.reset();}let originX, originY, trail =[], isMouseDown =false;this.slider.addEventListener('mousedown',function(e){ originX = e.x; originY = e.y; isMouseDown =true;}); document.addEventListener('mousemove',(e)=>{if(!isMouseDown)returnfalse;const moveX = e.x - originX;const moveY = e.y - originY;if(moveX <0|| moveX +38>= w)returnfalse;this.slider.style.left = moveX +'px';var blockLeft =(w -40-20)/(w -40)* moveX;this.block.style.left = blockLeft +'px';addClass(this.sliderContainer,'slider-container-active');this.sliderMask.style.width = moveX +'px'; trail.push(moveY);}); document.addEventListener('mouseup',(e)=>{if(!isMouseDown)returnfalse; isMouseDown =false;if(e.x == originX)returnfalse;removeClass(this.sliderContainer,'slider-container-active');this.trail = trail;const spliced =this.verify();if(spliced){addClass(this.sliderContainer,'slider-container-success');this.success &&this.success();}else{addClass(this.sliderContainer,'slider-container-fail');this.fail &&this.fail();setTimeout(()=>{this.reset();},1000);}});}// 重置reset(){this.sliderContainer.className ='slider-container';this.slider.style.left =0;this.block.style.left =0;this.sliderMask.style.width =0;this.clean();this.img.src =getRandomImg();this.draw();}// 验证verify(){const left =parseInt(this.block.style.left);//10表示容错率,值越小,需要拼得越精确return Math.abs(left -this.x)<10;}} win.captcha ={init:function(element, success, fail){newcaptcha(element, success, fail).init();}}}(window));
style
*{margin: 0;padding: 0;background-color: #333333;}body{/* 方便演示,满屏居中 */height: 100vh;display: flex;justify-content: center;align-items: center;}/* 小拼图 */.block{position: absolute;left: 0;top: 0;}/* 滑动条 */.slider-container{position: relative;text-align: center;width: 310px;height: 40px;line-height: 40px;margin-top: 15px;background-color: #f7f9fa;color: #45454c;border: 1px solid #e4e7eb;}.slider-mask{position: absolute;left: 0;top: 0;height: 40px;border: 0px solid #1991fa;background-color: #d1e9fe;}.slider{position: absolute;left: 0;top: 0;width: 40px;height: 40px;background: #fff;box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);cursor: pointer;transition: background 0.2s linear;}.slider-icon{position: absolute;left: 13px;top: 15px;width: 14px;height: 10px;background:url(/images/icon_light.png) 0 -26px;background-size: 34px 471px;}/* 滑动条活动态 */.slider-container-active .slider{height: 38px;top: -1px;border: 1px solid #1991fa;}.slider-container-active .slider-mask{height: 38px;border-width: 1px;}/* 滑动条成功态 */.slider-container-success .slider{height: 38px;top: -1px;border: 1px solid #52ccba;background-color: #52ccba !important;}.slider-container-success .slider-mask{height: 38px;border: 1px solid #52ccba;background-color: #d2f4ef;}/* 成功图标 */.slider-container-success .slider-icon{background-position: 0 0 !important;}/* 滑动条失败态 */.slider-container-fail .slider{height: 38px;top: -1px;border: 1px solid #f57a7a;background-color: #f57a7a !important;}.slider-container-fail .slider-mask{height: 38px;border: 1px solid #f57a7a;background-color: #fce1e1;}/* 失败图标 */.slider-container-fail .slider-icon{background-position: 0 -83px !important;}.slider-container-active .slider-text, .slider-container-success .slider-text, .slider-container-fail .slider-text{display: none;}.slider:hover{background: #1991fa;}.slider:hover .slider-icon{background-position: 0 -13px;}.refresh-icon{position: absolute;right: 0;top: 0;width: 34px;height: 34px;background:url(/images/icon_light.png) 0 -437px;background-size: 34px 471px;cursor: pointer;}#msg{height: 20px;line-height: 20px;text-align: center;margin-top: 15px;}
本文转载自: https://blog.csdn.net/weixin_51157081/article/details/122976165
版权归原作者 牧码人MJ682517 所有, 如有侵权,请联系我们删除。发表评论
“web前端之行为验证码、不同设备和屏幕尺寸呈现不同大小、元素宽度根据视口宽度进行调整、元素或图片裁剪、图片验证码”的评论:
还没有评论