当前位置:首页 » 《资源分享》 » 正文

web前端之行为验证码、不同设备和屏幕尺寸呈现不同大小、元素宽度根据视口宽度进行调整、元素或图片裁剪、图片验证码

13 人参与  2024年04月19日 13:44  分类 : 《资源分享》  评论

点击全文阅读


MENU

前言版本一(html+JS+css)版本二(html+JS+css+canvas)


前言

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>    <div class="clip_path"></div>    <div class="clip_path"></div></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部分
两个<div>元素被包含在一个外部<div>中。
每个<div>元素都有类名为clip_path,因此它们都受到了相同的CSS样式的影响。


综上所述,代码将显示两个相同大小的红色方块,但第一个方块的背景颜色为蓝色,并具有一种剪切路径,使其内部形成一个圆角矩形区域。


案例一效果图

case11


案例二(clamp最大值最小值的应用)

<style>.clamp {width: clamp(300px, 50vw, 600px);height: 300px;background-color: #ff0000;}</style><div class="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;设置元素的背景颜色为红色。


<div class=“clamp”></div>是一个HTML<div>元素,它具有一个类名为"clamp",因此应用了上述定义的CSS样式。这个<div>元素将具有限制宽度的特性,宽度将根据视窗宽度和定义的最小和最大宽度进行调整,以便在不同设备和屏幕尺寸下呈现出不同的大小。


案例二效果图

case21


case22


功能效果图

imageverificationCodeV11


imageverificationCodeV12


imageverificationCodeV13


html

<div id="captcha">    <div id="handle">        <span onmousedown="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;function onmousedownFn() {    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)

效果图

imageverificationCodeV21


imageverificationCodeV22


imageverificationCodeV23


html

<div class="container">    <div id="captcha" style="position: relative;"></div>    <div id="msg"></div></div><script src="./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;    // 获取指定区间内的随机数    function getRandomNumberByRange(start, end) {        return Math.round(Math.random() * (end - start) + start);    }    // 创建元素    function createElement(tagName) {        return document.createElement(tagName);    }    // 创建画布    function createCanvas(width, height) {        const canvas = createElement('canvas');        canvas.width = width;        canvas.height = height;        return canvas;    }    // 获取随机图片    function getRandomImg() {        // 这个网站可以生成随机图片        return 'https://picsum.photos/300/150/?image=' + getRandomNumberByRange(0, 100);    }    // 创建图片    function createImg(onload) {        const img = createElement('img');        img.crossOrigin = 'Anonymous';        img.onload = onload;        img.onerror = () => {            img.src = getRandomImg();        }        img.src = getRandomImg();        return img;    }    // 添加样式    function addClass(tag, className) {        tag.classList.add(className);    }    // 移除样式    function removeClass(tag, className) {        tag.classList.remove(className);    }    // 绘制    function draw(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();    }    // 求和    function sum(x, y) {        return x + y;    }    // 求平方    function square(x) {        return x * x;    }    // 验证码类    class captcha {        // 构造器        constructor(el, success, fail) {            this.el = el;            this.success = success;            this.fail = fail;        }        // 初始化        init() {            this.initDOM();            this.initImg();            this.draw();            this.bindEvents();        }        // 初始化DOM        initDOM() {            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) return false;                const moveX = e.x - originX;                const moveY = e.y - originY;                if (moveX < 0 || moveX + 38 >= w) return false;                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) return false;                isMouseDown = false;                if (e.x == originX) return false;                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) {            new captcha(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;}

点击全文阅读


本文链接:http://zhangshiyu.com/post/97583.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1