欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue+elementui實現(xiàn)拖住滑塊拼圖驗證

 更新時間:2022年03月28日 14:50:28   作者:管火火火  
這篇文章主要為大家詳細介紹了vue+elementui實現(xiàn)拖住滑塊拼圖驗證,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

vue拖住滑塊拼圖驗證,以下是cavas直接寫的滑塊拼圖驗證碼,直接復制引用即可

?<template>
??<div id="puzzle" ref="puzzle" style="display:inline-block;">
??<!-- :style="'padding:' + 16*scale + 'px ' + 16*scale + 'px ' + 28*scale + 'px;border-radius:'+16*scale+'px;'" -->
????<div class="puzzle-container"
?????>
??????<div :style="'position:relative;overflow:hidden;width:'+ dataWidth +'px;'">
????????<div :style="'position:relative;width:' + dataWidth + 'px;height:' + dataHeight + 'px;'">
??????????<img
????????????id="scream"
????????????ref="scream"
????????????:src="imgRandom"
????????????:style="'width:' + dataWidth + 'px;height:' + dataHeight + 'px;'"
??????????/>
??????????<canvas id="puzzle-box" ref="puzzleBox" :width="dataWidth" :height="dataHeight"></canvas>
????????</div>
????????<div
??????????class="puzzle-lost-box"
??????????:style="'left:' + left_Num + 'px;width:' + dataWidth + 'px;height:' + dataHeight + 'px;'"
????????>
??????????<canvas id="puzzle-shadow" ref="puzzleShadow" :width="dataWidth" :height="dataHeight"></canvas>
??????????<canvas id="puzzle-lost" ref="puzzleLost" :width="dataWidth" :height="dataHeight"></canvas>
????????</div>
????????<p
??????????class="ver-tips"
??????????ref="verTips"
??????????:style="'height: '+22*scale+'px;line-height:'+22*scale+'px;bottom: ' + (displayTips==true ? 0 : -22*scale ) +'px;font-size: '+12*scale+'px;'"
????????>
??????????<template v-if="verification">
????????????<span :style="'color:#42ca6b;line-height:'+ 22*scale+'px;'">驗證通過</span>
????????????<span :style="'margin-left:'+4*scale+'px;line-height:'+ 22*scale+'px;'">哇喔,怪物吃了拼圖,快去登錄吧~</span>
??????????</template>
??????????<template v-if="!verification">
????????????<span :style="'color:red;line-height:'+22*scale+'px;'">驗證失敗:</span>
????????????<span :style="'margin-left:'+4*scale+'px;line-height:'+ 22*scale+'px;'">拖動滑塊將懸浮圖像正確拼合</span>
??????????</template>
????????</p>
??????</div>
??????<div
????????class="re-btn"
????????@click="refreshImg"
????????:style="'height: '+28*scale+'px;padding: '+1*scale+'px '+16*scale+'px;font-size: '+18*scale+'px;'"
??????>
????????<a-icon type="redo" />
??????</div>
????</div>
????<br />
????<div class="slider-container" :style="'width:' + dataWidth + 'px;'">
??????<div class="slider-bar" :style="'border-radius:'+ 24*scale+'px;'">
????????<p
??????????class="slider-bar-text select-none"
??????????onselectstart="return false"
??????????:style="'line-height:' + 28*scale + 'px;font-size:'+12*scale+'px;'"
????????>按住滑塊, 拖動完成上方拼圖</p>
??????</div>
??????<div
????????class="slider-btn"
????????ref="sliderBtn"
????????@mousedown="startMove"
????????@touchstart="startMove"
????????:style="'top: '+ -7*scale + 'px;'"
??????>
????????<a-icon
??????????type="pause-circle"
??????????theme="twoTone"
??????????twoToneColor="#52c41a"
??????????:style="'font-size: '+44*scale+'px;'"
????????/>
????????<span class="slider-center-zzz">▍▍▍</span>
??????</div>
????</div>
??</div>
</template>

<script lang="js">

export default {
??name: 'puzzle',
??data () {
????return {
??????moveStart: '',
??????displayTips: false,
??????verification: false,
??????randomX: null,
??????randomY: null,
??????imgRandom: '',
??????left_Num: 0,
??????dataWidth: 404,
??????dataHeight: 90,
??????puzzleSize: 100,
??????deviation: 11,
??????scale: 1,
??????reTimer: null,
??????isleavePage: false
????}
??},
??props: {
????width: {
??????type: [String, Number],
??????default: 340
????},
????height: {
??????type: [String, Number],
??????default: 120
????},
????cropImage: {
??????type: [Boolean],
??????default: false
????},
????puzzleImgList: {
??????type: Array,
??????default: () => [
????????'../../../static/img/a.png',
??????]
????},
????PlSize: {
??????type: [String, Number],
??????default: 48
????},
????Deviation:{
??????type: [String, Number],
??????default: 4
????},
????padding: {
??????type: [Number],
??????default: 20
????},
????onSuccess: {
??????type: Function,
??????default: () => {
????????alert('驗證成功')
??????}
????},
????onError: {
??????type: Function,
??????default: () => {
????????alert('驗證失敗')
??????}
????}
??},
??methods: {
????/* 刷新 */
????RandomNum(Min, Max) {
??????let Range = Max - Min + 1
??????let Rand = Math.random()
??????return Min + Math.floor(Rand * Range)
????},
????refreshImg () {
??????let imgRandomNum = this.RandomNum(0, this.puzzleImgList.length-1)
??????this.imgRandom = this.puzzleImgList[imgRandomNum]
??????this.initCanvas()
????},
????/* 畫布初始化 */
????initCanvas () {
??????this.clearCanvas()

??????// let self = this
??????let w = this.dataWidth
??????let h = this.dataHeight
??????// let PL_Size = 48
??????// 2019-02-12開始PL_Size使用可傳遞參數(shù)
??????let PL_Size = this.puzzleSize
??????let padding = 20
??????let MinN_X = padding + PL_Size
??????let MaxN_X = w - padding - PL_Size - PL_Size / 6
??????let MaxN_Y = padding
??????let MinN_Y = h - padding - PL_Size - PL_Size / 6
??????this.randomX = this.RandomNum(MinN_X, MaxN_X)
??????this.randomY = this.RandomNum(MinN_Y, MaxN_Y)
??????let X = this.randomX
??????let Y = this.randomY
??????this.left_Num = -X + 10
??????let d = PL_Size / 3

??????let c = this.$refs.puzzleBox
??????let c_l = this.$refs.puzzleLost
??????let c_s = this.$refs.puzzleShadow
??????let ctx = c.getContext('2d')
??????let ctx_l = c_l.getContext('2d')
??????let ctx_s = c_s.getContext('2d')
??????ctx.globalCompositeOperation = 'xor'
??????ctx.shadowBlur = 10
??????ctx.shadowColor = '#fff'
??????ctx.shadowOffsetX = 3
??????ctx.shadowOffsetY = 3
??????ctx.fillStyle = 'rgba(0,0,0,0.7)'
??????ctx.beginPath()
??????ctx.lineWidth = '1'
??????ctx.strokeStyle = 'rgba(0,0,0,0)'
??????ctx.moveTo(X, Y)
??????ctx.lineTo(X + d, Y)
??????ctx.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y)
??????ctx.lineTo(X + 3 * d, Y)
??????ctx.lineTo(X + 3 * d, Y + d)
??????ctx.bezierCurveTo(X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d)
??????ctx.lineTo(X + 3 * d, Y + 3 * d)
??????ctx.lineTo(X, Y + 3 * d)
??????ctx.closePath()
??????ctx.stroke()
??????ctx.fill()

??????let img = new Image()
??????img.src = this.imgRandom
??????img.onload = function () {
????????ctx_l.beginPath()
????????ctx_l.strokeStyle = 'rgba(0,0,0,0)'
????????ctx_l.moveTo(X, Y)
????????ctx_l.lineTo(X + d, Y)
????????ctx_l.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y)
????????ctx_l.lineTo(X + 3 * d, Y)
????????ctx_l.lineTo(X + 3 * d, Y + d)
????????ctx_l.bezierCurveTo(X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d)
????????ctx_l.lineTo(X + 3 * d, Y + 3 * d)
????????ctx_l.lineTo(X, Y + 3 * d)
????????ctx_l.closePath()
????????ctx_l.stroke()
????????ctx_l.shadowBlur = 10
????????ctx_l.shadowColor = 'black'
????????ctx_l.clip()
????????ctx_l.drawImage(img, 0, 0, w, h)

??????}
??????ctx_s.beginPath()
??????ctx_s.lineWidth = '1'
??????ctx_s.strokeStyle = 'rgba(0,0,0,0)'
??????ctx_s.moveTo(X, Y)
??????ctx_s.lineTo(X + d, Y)
??????ctx_s.bezierCurveTo(X + d, Y - d, X + 2 * d, Y - d, X + 2 * d, Y)
??????ctx_s.lineTo(X + 3 * d, Y)
??????ctx_s.lineTo(X + 3 * d, Y + d)
??????ctx_s.bezierCurveTo(X + 2 * d, Y + d, X + 2 * d, Y + 2 * d, X + 3 * d, Y + 2 * d)
??????ctx_s.lineTo(X + 3 * d, Y + 3 * d)
??????ctx_s.lineTo(X, Y + 3 * d)
??????ctx_s.closePath()
??????ctx_s.stroke()
??????ctx_s.shadowBlur = 20
??????ctx_s.shadowColor = 'black'
??????ctx_s.fill()
????},
????/* 通過重置畫布尺寸清空畫布,這種方式更徹底 */
????clearCanvas () {
??????let c = this.$refs.puzzleBox
??????let c_l = this.$refs.puzzleLost
??????let c_s = this.$refs.puzzleShadow
??????c.setAttribute('height', c.getAttribute('height'))
??????c_l.setAttribute('height', c.getAttribute('height'))
??????c_s.setAttribute('height', c.getAttribute('height'))
??????// c.height = c.height
??????// c_l.height = c_l.height
??????// c_s.height = c_s.height
????},
????/* 按住滑塊后初始化移動監(jiān)聽,記錄初始位置 */
????startMove (e) {
??????console.log(e)
??????e = e || window.event
??????this.$refs.sliderBtn.style.backgroundPosition = '0 -216px'
??????this.moveStart = e.pageX || e.targetTouches[0].pageX
??????this.addMouseMoveListener()
????},
????/* 滑塊移動 */
????moving (e) {
??????let self = this
??????e = e || window.event
??????let moveX = e.pageX || e.targetTouches[0].pageX
??????let d = moveX - self.moveStart
??????let w = self.dataWidth
??????let PL_Size = this.puzzleSize
??????let padding = 20
??????if (self.moveStart === '') {
????????return ''
??????}
??????if (d < 0 || d > (w - padding - PL_Size)) {
????????return ''
??????}
??????self.$refs.sliderBtn.style.left = d + 'px'
??????self.$refs.sliderBtn.style.transition = 'inherit'
??????self.$refs.puzzleLost.style.left = d + 'px'
??????self.$refs.puzzleLost.style.transition = 'inherit'
??????self.$refs.puzzleShadow.style.left = d + 'px'
??????self.$refs.puzzleShadow.style.transition = 'inherit'
????},
????/* 移動結(jié)束,驗證并回調(diào) */
????moveEnd (e) {
??????let self = this
??????e = e || window.event
??????let moveEnd_X = (e.pageX || e.changedTouches[0].pageX) - self.moveStart
??????let ver_Num = self.randomX - 10
??????let deviation = this.deviation
??????let Min_left = ver_Num - deviation
??????let Max_left = ver_Num + deviation
??????if (self.moveStart !== '') {
????????if (Max_left > moveEnd_X && moveEnd_X > Min_left) {
????????????
??????????self.displayTips = true
??????????self.verification = true
??????????setTimeout(function () {
????????????if(self.isleavePage){
??????????????return
????????????}
????????????self.displayTips = false
????????????self.initCanvas()
??????????}, 2000)
??????????/* 成功的回調(diào)函數(shù) */
??????????self.onSuccess()
????????} else {
??????????self.displayTips = true
??????????self.verification = false
??????????setTimeout(function () {
????????????if(self.isleavePage){
??????????????return
????????????}
????????????self.displayTips = false
??????????}, 2000)
??????????/* 失敗的回調(diào)函數(shù) */
??????????self.onError()
????????}
??????}
??????if (typeof(self.$refs.sliderBtn) !== 'undefined' && typeof (self.$refs.puzzleLost) !== 'undefined' && typeof (self.$refs.puzzleShadow) !== 'undefined') {
????????self.reTimer = setTimeout(function () {
??????????if(self.isleavePage){
????????????return
??????????}
??????????self.$refs.sliderBtn.style.left = 0
??????????self.$refs.sliderBtn.style.transition = 'left 0.5s'
??????????self.$refs.puzzleLost.style.left = 0
??????????self.$refs.puzzleLost.style.transition = 'left 0.5s'
??????????self.$refs.puzzleShadow.style.left = 0
??????????self.$refs.puzzleShadow.style.transition = 'left 0.5s'
????????}, 1000)
????????self.$refs.sliderBtn.style.backgroundPosition = '0 -84px'
??????}
??????self.moveStart = ''
????},
????/* 綁定滑塊移動與滑動結(jié)束,移動過程中鼠標可在綁定的區(qū)域 */
????addMouseMoveListener () {
??????let self = this
??????document.addEventListener('mousemove', self.moving)
??????document.addEventListener('touchmove', self.moving)
??????document.addEventListener('mouseup', self.moveEnd)
??????document.addEventListener('touchend', self.moveEnd)
????}

??},
??mounted () {
????let self = this
????this.dataWidth = this.$refs.puzzle.clientWidth*0.884
????this.dataHeight = this.dataWidth*(this.height/this.width)
????this.scale = this.$refs.puzzle.clientWidth/260
????this.puzzleSize = this.dataWidth*(this.PlSize/this.width)
????setTimeout(self.refreshImg,0)
??},
??created () {
????let imgRandomNum = this.RandomNum(0, this.puzzleImgList.length - 1)
????this.imgRandom = this.puzzleImgList[imgRandomNum]
????this.puzzleSize = Number(this.PlSize)
????this.deviation = Number(this.Deviation)
????
????// this.dataWidth = this.width
????// this.dataHeight = this.height
????// this.scale = this.width/260
??},
??watch: {
??},
??beforeDestroy() {
????this.isleavePage = true
??}
}
</script>

<style scoped>
.slider-btn {
??position: absolute;
??width: 90px;
??height: 67px;
??left: 0;
??top: -7px;
??z-index: 12;
??cursor: pointer;
??background-position: 0 -84px;
??transition: inherit;
??background-color: #f4f7fe;
??border-radius: 45%;
??display: flex;
}
.slider-center-zzz {
??text-align: center;
??line-height: 67px;
??position: absolute;
??color: #53C300;
??height: 40px;
??width: 100%;
}
.ver-tips {
??position: absolute;
??left: 0;
??bottom: -22px;
??background: rgba(255, 255, 255, 0.9);
??height: 22px;
??line-height: 22px;
??font-size: 12px;
??width: 100%;
??margin: 0;
??text-align: left;
??padding: 0 8px;
??transition: all 0.4s;
}
.slider-tips {
??bottom: 0;
}
.ver-tips i {
??display: inline-block;
??width: 22px;
??height: 22px;
??vertical-align: top;
??background-position: -4px -1229px;
}
.ver-tips span {
??display: inline-block;
??vertical-align: top;
??line-height: 22px;
??color: #455;
}
.active-tips {
??display: block;
}
.hidden {
??display: none;
}
.re-btn {
??position: absolute;
??left: 0;
??bottom: 0;
??height: 28px;
??padding: 0 16px;
}
.re-btn a {
??display: inline-block;
??width: 14px;
??height: 14px;
??margin: 0px 0;
??background-position: 0 -1179px;
??cursor: pointer;
}
.re-btn a:hover {
??background-position: 0 -1193px;
}

.puzzle-container {
??position: relative;
??/* padding: 16px 16px 28px; */
??/* border: 1px solid #ddd; */
??background: #e0e1e3;
??/* border-radius: 16px; */

??/* height: 83px; ?*/
??/* width: 340px; */
}
.slider-container {
??position: relative;
??margin: auto;
}
.slider-bar {
??border: 1px solid #c3c3c3;
??border-radius: 24px;
??background: #e0e1e3;
??box-shadow: 0 1px 1px rgba(12, 10, 10, 0.2) inset;
}
.slider-bar-text {
??font-size: 12px;
??color: #486c80;
??line-height: 28px;
??margin: 0;
??text-align: right;
??padding-right: 22px;
}

#puzzle-box {
??position: absolute;
??left: 0;
??top: 0;
??z-index: 22;
}
#puzzle-shadow {
??position: absolute;
??left: 0;
??top: 0;
??z-index: 22;
}
#puzzle-lost {
??position: absolute;
??left: 0;
??top: 0;
??z-index: 33;
}
.puzzle-lost-box {
??position: absolute;
??width: 260px;
??height: 116px;
??left: 0;
??top: 0;
??z-index: 111;
}
</style>

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Vue中如何實現(xiàn)在線預覽word文件、excel文件

    Vue中如何實現(xiàn)在線預覽word文件、excel文件

    這篇文章主要介紹了Vue中如何實現(xiàn)在線預覽word文件、excel文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • vue2和vue3的v-if與v-for優(yōu)先級對比學習

    vue2和vue3的v-if與v-for優(yōu)先級對比學習

    這篇文章主要介紹了vue2和vue3的v-if與v-for優(yōu)先級對比學習,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • 解決vue處理axios post請求傳參的問題

    解決vue處理axios post請求傳參的問題

    下面小編就為大家分享一篇解決vue處理axios post請求傳參的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue項目前端微信JSAPI與外部H5支付相關實現(xiàn)過程及常見問題

    vue項目前端微信JSAPI與外部H5支付相關實現(xiàn)過程及常見問題

    這篇文章主要介紹了vue項目前端微信JSAPI與外部H5支付相關實現(xiàn)過程及常見問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • 從vue基礎開始創(chuàng)建一個簡單的增刪改查的實例代碼(推薦)

    從vue基礎開始創(chuàng)建一個簡單的增刪改查的實例代碼(推薦)

    這篇文章主要介紹了從vue基礎開始創(chuàng)建一個簡單的增刪改查的實例代碼,需要的朋友參考下
    2018-02-02
  • 基于Vue3和Plotly.js實現(xiàn)交互式3D圖

    基于Vue3和Plotly.js實現(xiàn)交互式3D圖

    這篇文章主要介紹了基于Vue3和Plotly.js實現(xiàn)交互式3D圖,本代碼旨在為數(shù)據(jù)可視化提供一個交互式圖表,允許用戶動態(tài)控制圖表中線條的顏色和可見性,此功能對于探索大型數(shù)據(jù)集或突出特定數(shù)據(jù)子集非常有用,需要的朋友可以參考下
    2024-07-07
  • vue動態(tài)生成dom并且自動綁定事件

    vue動態(tài)生成dom并且自動綁定事件

    本篇文章主要介紹了vue動態(tài)生成dom并且自動綁定事件,具有一定的參考價值,有興趣的可以了解一下。
    2017-04-04
  • 如何解決vuex在頁面刷新后數(shù)據(jù)被清除的問題

    如何解決vuex在頁面刷新后數(shù)據(jù)被清除的問題

    這篇文章主要介紹了如何解決vuex在頁面刷新后數(shù)據(jù)被清除的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 保姆級Vue3開發(fā)教程分享

    保姆級Vue3開發(fā)教程分享

    這篇Vue3開發(fā)文檔,包含了 Vue3 開發(fā)中使用的所有語法,文中的示例代碼講解詳細,希望所有像他一樣還不熟的伙伴快速上手 Vue3,不會的再不看要遭老罪咯
    2023-04-04
  • elementPlus?的el-select在提示框關閉時自動彈出的問題解決

    elementPlus?的el-select在提示框關閉時自動彈出的問題解決

    這篇文章主要介紹了elementPlus?的el-select在提示框關閉時自動彈出閉時自動彈出的問題,主要問題就是因為filterable屬性,根本解決方案是選中的時候讓他失去焦點?el-select有一個visible-change事件,下拉框出現(xiàn)/隱藏時觸發(fā),感興趣的朋友跟隨小編一起看看吧
    2024-01-01

最新評論