中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

終于實現滑動拼圖驗證碼,vue

發布時間:2020-09-24 13:16:32 來源:網絡 閱讀:2479 作者:可樂程序員 欄目:web開發

緣由:之前看嗶哩嗶哩官網登錄的時候有一個拼圖驗證碼,很好奇怎么去實現。然后就想著自己弄一個。先給大家看我的最終效果。后面再一點點拆解代碼。

終于實現滑動拼圖驗證碼,vue


為什么想著寫這個功能呢,主要在于拼圖驗證碼在前端這里會比較復雜并且深入。相比文字拼寫,12306的圖片驗證碼都沒有拼圖驗證碼對前端的要求來的復雜,和難。

我總結下知識點:

1、彈窗功能

2、彈窗基于元素定位

3、元素拖動

4、canvas繪圖

5、基礎邏輯

一、彈窗和彈窗組件

抱歉,這里我偷懶了直接用了elementUI的el-popover組件,所以小伙伴不懂的直接看elementUI官網的說明。

我個人也研究和編寫了這塊的組件功能(基于popper.js)

二、編寫基礎結構

這塊屬于html的基礎內容,也就標題黨了

三、canvas繪制圖片

1、canvas繪制外部img圖片

代碼:

let?mainDom?=?document.querySelector("#codeImg");let?bg?=?mainDom.getContext("2d");let?width?=?mainDom.width;let?height?=?mainDom.height;let?blockDom?=?document.querySelector("#sliderBlock");let?block?=?blockDom.getContext("2d");
//重新賦值,讓canvas進行重新繪制
blockDom.height?=?height;
mainDom.height?=?height;let?imgsrc?=?require("../assets/images/back.jpg");let?img?=?document.createElement("img");
img.style.objectFit?=?"scale-down";
img.src?=?imgsrc;
img.onload?=?function()?{
?bg.drawImage(img,?0,?0,?width,?height);?block.drawImage(img,?0,?0,?width,?height);
};復制代碼

這里我繪制了兩個canvas,因為一個是背景一個是滑塊

核心在于

let?mainDom?=?document.querySelector("#codeImg");let?imgsrc?=?require("../assets/images/back.jpg");let?bg?=?mainDom.getContext("2d");let?img?=?document.createElement("img");
img.onload?=?function()?{
?bg.drawImage(img,?0,?0,?width,?height);
};
復制代碼

2、canvas繪制滑塊部分

就是這個圖,這個有一些知識點,不難,但是很復雜。

終于實現滑動拼圖驗證碼,vue


代碼部分:

drawBlock(ctx,?xy?=?{?x:?254,?y:?109,?r:?9?},?type)?{
?let?x?=?xy.x,
?y?=?xy.y,
?r?=?xy.r,
?w?=?40;
?let?PI?=?Math.PI;?//繪制
?ctx.beginPath();?//left
?ctx.moveTo(x,?y);?//top
?ctx.arc(x?+?(w?+?5)?/?2,?y,?r,?-PI,?0,?true);
?ctx.lineTo(x?+?w?+?5,?y);?//right
?ctx.arc(x?+?w?+?5,?y?+?w?/?2,?r,?1.5?*?PI,?0.5?*?PI,?false);
?ctx.lineTo(x?+?w?+?5,?y?+?w);?//bottom
?ctx.arc(x?+?(w?+?5)?/?2,?y?+?w,?r,?0,?PI,?false);
?ctx.lineTo(x,?y?+?w);
?ctx.arc(x,?y?+?w?/?2,?r,?0.5?*?PI,?1.5?*?PI,?true);
?ctx.lineTo(x,?y);?//修飾,沒有會看不出效果
?ctx.lineWidth?=?1;
?ctx.fillStyle?=?"rgba(255,?255,?255,?0.5)";
?ctx.strokeStyle?=?"rgba(255,?255,?255,?0.5)";
?ctx.stroke();
?ctx[type]();
?ctx.globalCompositeOperation?=?"xor";
}復制代碼

解釋下:

參數是傳入canvas對象

x,y軸數據

剪切還是填充的canvas函數(fill,clip)

繪制難點:(很重要,不然你沒法理解它怎么繪制的)

繪制主要是需要理解這里的繪制是根據你設置一個起始點坐標,然后你繪制第二次的時候線就會連接到第二個點,依次連接最后回到原點就形成一個完整的圖形。

終于實現滑動拼圖驗證碼,vue


用的是arc參數,主要是看這個圖

fill是用于填充繪制的部分,clip是裁剪出繪制的部分,利用這個就可以出現一個扣掉的圖片和一個裁剪出來的圖片。

完成之后就是我的那個函數了。大家可以直接拿去用。

3、讓元素跟隨鼠標點擊之后滑動

這里其實原理非常簡單,就是有一個注意點。

原理:

鼠標點擊之后記錄當前坐標,然后隨著(mousemove)滾動的時候修改元素的left和top值就行了。

還有一點就是鼠標快速滑動會導致丟失滑動效果,這里需要用document,不能是元素級別的監聽。

元素上面我只需要鑒定按下mousedown

代碼:

//鼠標按下drag(e)?{?console.log("鼠標按下",?e);?let?dom?=?e.target;?//dom元素
?let?slider?=?document.querySelector("#sliderBlock");?//滑塊dom
?const?downCoordinate?=?{?x:?e.x,?y:?e.y?};?//正確的滑塊數據
?let?checkx?=?Number(this.slider.mx)?-?Number(this.slider.bx);?//x軸數據
?let?x?=?0;?const?move?=?moveEV?=>?{
?x?=?moveEV.x?-?downCoordinate.x;?//y?=?moveEV.y?-?downCoordinate.y;
?if?(x?>=?251?||?x?<=?0)?return?false;
?dom.style.left?=?x?+?"px";?//dom.style.top?=?y?+?"px";
?slider.style.left?=?x?+?"px";
?};?const?up?=?()?=>?{?document.removeEventListener("mousemove",?move);?document.removeEventListener("mouseup",?up);
?dom.style.left?=?"";?console.log(x,?checkx);?let?max?=?checkx?-?5;?let?min?=?checkx?-?10;?//允許正負誤差1
?if?((max?>=?x?&&?x?>=?min)?||?x?===?checkx)?{?console.log("滑動解鎖成功");?this.puzzle?=?true;?this.tips?=?"驗證成功";
?setTimeout(()?=>?{?this.visible?=?false;
?},?500);
?}?else?{?console.log("拼圖位置不正確");?this.tips?=?"驗證失敗,請重試";?this.puzzle?=?false;?this.canvasInit();
?}
?};?document.addEventListener("mousemove",?move);?document.addEventListener("mouseup",?up);
}復制代碼

4、總結

核心點比較多,寫過之后發現不難,關鍵在于去寫

個人該頁面git地址:https://github.com/ht-sauce/dream

該頁面處于項目的

終于實現滑動拼圖驗證碼,vue


路由訪問為:http://localhost:8080/consumer

5、完整的頁面代碼

<template>
?<div?id="login">
?<el-form?class="loginFrom"?:model="logindata"?:rules="rules"?ref="ruleForm">
?<el-form-item?class="login-item">
?<h2?class="login-title">海天醬油登錄中心</h2>
?</el-form-item>
?<el-form-item?prop="userName">
?<el-input
?class="login-inputorbuttom"
?prefix-icon="el-icon-user"
?placeholder="登錄名"
?v-model="logindata.userName"
?></el-input>
?</el-form-item>
?<el-form-item?prop="password">
?<el-input
?class="login-inputorbuttom"
?prefix-icon="el-icon-lock"
?placeholder="密碼"
?v-model="logindata.password"
?></el-input>
?</el-form-item>
?<!--<el-form-item?prop="verificationCode">
?<el-input
?class="login-inputorbuttom"
?v-model="logindata.verificationCode"
?></el-input>
?</el-form-item>-->
?<el-form-item?class="login-item">
?<el-button
?class="login-inputorbuttom?login-bottom"
?type="primary"
?v-popover:popover
?@click="visible?=?!visible"
?>登?錄</el-button
?>
?</el-form-item>
?</el-form>
?<!--驗證碼彈窗-->
?<el-popover
?popper-class="slidingPictures"
?ref="popover"
?trigger="manual"
?v-model="visible"
?>
?<div?class="sliding-pictures">
?<div?class="vimg">
?<canvas?id="sliderBlock"></canvas>
?<canvas?id="codeImg"></canvas>
?</div>
?<div?class="slider">
?<div?class="track"?:class="{?pintuTrue:?puzzle?}">
?{{?tips?}}
?</div>
?<div?class="button?el-icon-s-grid"?@mousedown.prevent="drag"></div>
?</div>
?<div?class="operation">
?<span
?title="關閉驗證碼"
?@click="visible?=?false"
?class="el-icon-circle-close"
?></span>
?<span
?title="刷新驗證碼"
?@click="canvasInit"
?class="el-icon-refresh-left"
?></span>
?</div>
?</div>
?</el-popover>
?</div></template><script>export?default?{?name:?"login",
?data()?{?return?{?tips:?"拖動左邊滑塊完成上方拼圖",?logindata:?{?userName:?"",?password:?"",?verificationCode:?""
?},?rules:?{},?visible:?false,?//滑塊x軸數據
?slider:?{?mx:?0,?bx:?0
?},?//拼圖是否正確
?puzzle:?false
?};
?},?watch:?{
?visible(e)?{?if?(e?===?true)?{?this.canvasInit();?this.puzzle?=?false;
?}
?}
?},
?beforeCreate()?{},
?created()?{},
?beforeMount()?{},
?mounted()?{},?methods:?{?//拼圖驗證碼初始化
?canvasInit()?{?//生成指定區間的隨機數
?const?random?=?(min,?max)?=>?{?return?Math.floor(Math.random()?*?(max?-?min?+?1)?+?min);
?};?//x:?254,?y:?109
?let?mx?=?random(127,?244),
?bx?=?random(10,?128),
?y?=?random(10,?99);?this.slider?=?{?mx,?bx?};?this.draw(mx,?bx,?y);
?},?//鼠標按下
?drag(e)?{?console.log("鼠標按下",?e);?let?dom?=?e.target;?//dom元素
?let?slider?=?document.querySelector("#sliderBlock");?//滑塊dom
?const?downCoordinate?=?{?x:?e.x,?y:?e.y?};?//正確的滑塊數據
?let?checkx?=?Number(this.slider.mx)?-?Number(this.slider.bx);?//x軸數據
?let?x?=?0;?const?move?=?moveEV?=>?{
?x?=?moveEV.x?-?downCoordinate.x;?//y?=?moveEV.y?-?downCoordinate.y;
?if?(x?>=?251?||?x?<=?0)?return?false;
?dom.style.left?=?x?+?"px";?//dom.style.top?=?y?+?"px";
?slider.style.left?=?x?+?"px";
?};?const?up?=?()?=>?{?document.removeEventListener("mousemove",?move);?document.removeEventListener("mouseup",?up);
?dom.style.left?=?"";?console.log(x,?checkx);?let?max?=?checkx?-?5;?let?min?=?checkx?-?10;?//允許正負誤差1
?if?((max?>=?x?&&?x?>=?min)?||?x?===?checkx)?{?console.log("滑動解鎖成功");?this.puzzle?=?true;?this.tips?=?"驗證成功";
?setTimeout(()?=>?{?this.visible?=?false;
?},?500);
?}?else?{?console.log("拼圖位置不正確");?this.tips?=?"驗證失敗,請重試";?this.puzzle?=?false;?this.canvasInit();
?}
?};?document.addEventListener("mousemove",?move);?document.addEventListener("mouseup",?up);
?},
?draw(mx?=?200,?bx?=?20,?y?=?50)?{?let?mainDom?=?document.querySelector("#codeImg");?let?bg?=?mainDom.getContext("2d");?let?width?=?mainDom.width;?let?height?=?mainDom.height;?let?blockDom?=?document.querySelector("#sliderBlock");?let?block?=?blockDom.getContext("2d");?//重新賦值,讓canvas進行重新繪制
?blockDom.height?=?height;
?mainDom.height?=?height;?let?imgsrc?=?require("../assets/images/back.jpg");?let?img?=?document.createElement("img");
?img.style.objectFit?=?"scale-down";
?img.src?=?imgsrc;
?img.onload?=?function()?{
?bg.drawImage(img,?0,?0,?width,?height);
?block.drawImage(img,?0,?0,?width,?height);
?};?let?mainxy?=?{?x:?mx,?y:?y,?r:?9?};?let?blockxy?=?{?x:?bx,?y:?y,?r:?9?};?this.drawBlock(bg,?mainxy,?"fill");?this.drawBlock(block,?blockxy,?"clip");
?},?//繪制拼圖
?drawBlock(ctx,?xy?=?{?x:?254,?y:?109,?r:?9?},?type)?{?let?x?=?xy.x,
?y?=?xy.y,
?r?=?xy.r,
?w?=?40;?let?PI?=?Math.PI;?//繪制
?ctx.beginPath();?//left
?ctx.moveTo(x,?y);?//top
?ctx.arc(x?+?(w?+?5)?/?2,?y,?r,?-PI,?0,?true);
?ctx.lineTo(x?+?w?+?5,?y);?//right
?ctx.arc(x?+?w?+?5,?y?+?w?/?2,?r,?1.5?*?PI,?0.5?*?PI,?false);
?ctx.lineTo(x?+?w?+?5,?y?+?w);?//bottom
?ctx.arc(x?+?(w?+?5)?/?2,?y?+?w,?r,?0,?PI,?false);
?ctx.lineTo(x,?y?+?w);
?ctx.arc(x,?y?+?w?/?2,?r,?0.5?*?PI,?1.5?*?PI,?true);
?ctx.lineTo(x,?y);?//修飾,沒有會看不出效果
?ctx.lineWidth?=?1;
?ctx.fillStyle?=?"rgba(255,?255,?255,?0.5)";
?ctx.strokeStyle?=?"rgba(255,?255,?255,?0.5)";
?ctx.stroke();
?ctx[type]();
?ctx.globalCompositeOperation?=?"xor";
?}
?}
};</script><style>.slidingPictures?{?padding:?0;?width:?300px;?border-radius:?2px;
}</style><style?scoped?lang="scss"></style>

最后

喜歡的可以點個關注嗎,小可樂也不容易呢

終于實現滑動拼圖驗證碼,vue



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武宁县| 嘉善县| 鲁甸县| 连江县| 东丰县| 诸暨市| 龙州县| 滨州市| 宝应县| 介休市| 天峨县| 双峰县| 休宁县| 安化县| 洛扎县| 措美县| 通州市| 民权县| 临武县| 马鞍山市| 湖北省| 华坪县| 格尔木市| 张家港市| 朔州市| 手机| 理塘县| 罗江县| 怀集县| 当涂县| 金平| 化州市| 鸡西市| 县级市| 峨山| 惠州市| 黔南| 灵宝市| 故城县| 新乡市| 民和|