最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue自定義開發(fā)滑動圖片驗證組件

 更新時間:2022年03月31日 13:12:17   作者:維多利亞少年-  
這篇文章主要為大家詳細介紹了vue自定義開發(fā)滑動圖片驗證組件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

純前端,通過canvas來自定義開發(fā)滑動圖片驗證,反過來也能完成純滑動驗證。

<template>
? <div class="verification" ref="verification">
? ? <!-- 畫布部分 -->
? ? <canvas ref="slideVerify" class="slide-img"></canvas>
? ? <div style="display:none">
? ? ? <img ref="imgs" :src="imgList[imgIndex]"/>
? ? </div>
? ? <!-- 下面滑塊部分 -->
? ? <div class="slide-wrapper bg-start">
? ? ? <!-- 滑塊 -->
? ? ? <div class="btn" ref="btn" @mousedown="mouseDown" @mouseup="mouseUp"></div>
? ? ? <p class="text" ref="text">{{content}}</p>
? ? ? <div class="bg" ref="bg"></div>
? ? </div>
? ? <!-- 刷新按鈕 -->
? ? <button class="refresh" @click="refresh"></button>
? </div>
</template>

<script>
export default {
? data () {
? ? return {
? ? ? imgIndex: 0,
? ? ? blockCanvas: null,
? ? ? imgList: [require('../assets/1.png'),
? ? ? ? require('../assets/3.png'),
? ? ? ? require('../assets/4.png'),
? ? ? ? require('../assets/5.png') ],
? ? ? content: '滑動滑塊',
? ? ? isDown: false, // 鼠標是否按下
? ? ? btnX: 0,?
? ? ? imgX: 0?
? ? }
? },
? mounted () {
? ? this.imgIndex = this.randomNumber(0, 4)
? ? document.addEventListener('mousemove', this.mouseMove)
? ? this.imageCanvas()
? },
? methods: {
? ? // 生成隨機數(shù)字
? ? randomNumber (min, max) {
? ? ? return Math.floor(Math.random() * (max - min) + min)
? ? },
? ? // 鼠標按下時
? ? mouseDown (e) {
? ? ? this.isDown = true
? ? ? this.btnX = e.clientX - this.$refs.btn.offsetLeft
? ? },
? ? // 鼠標滑動時
? ? mouseMove (e) {
? ? ? // 滑塊左端向右邊移動的距離
? ? ? let moveX = e.clientX - this.btnX
? ? ? if (this.isDown) {
? ? ? ? // 滑塊滑動時不能超過的距離
? ? ? ? if (this.$refs.btn.offsetLeft <= 259 && this.$refs.btn.offsetLeft >= 0) {
? ? ? ? ? this.$refs.btn.style.left = `${moveX}px`
? ? ? ? ? this.blockCanvas.style.left = `${moveX - this.imgX}px`
? ? ? ? ? this.$refs.bg.style.width = `${moveX}px`
? ? ? ? }
? ? ? }
? ? },
? ? // 滑動中松開
? ? mouseUp () {
? ? ? let leftX = this.$refs.btn.offsetLeft
? ? ? // 方塊的位置和缺失的位置重合允許左右2px的誤差
? ? ? if (this.imgX >= leftX - 1 && this.imgX <= leftX + 1) {
? ? ? ? // 滑動成功時的邏輯
? ? ? ? this.$refs.btn.classList.add('btnsuccess')
? ? ? ? this.isDown = false
? ? ? }
? ? ? // 如果滑動失敗,滑塊自動回到左邊
? ? ? if (this.isDown) {
? ? ? ? this.$refs.btn.style.left = 0
? ? ? ? this.blockCanvas.style.left = `-${this.imgX}px`
? ? ? ? this.$refs.bg.style.width = 0
? ? ? }
? ? ? // 開關原則
? ? ? this.isDown = false
? ? },
? ? // 畫圖
? ? imageCanvas () {
? ? ? this.blockCanvas = this.blockCanvas ? this.blockCanvas.remove() : null
? ? ? this.blockCanvas = this.createCanvas(300, 150)
? ? ? this.$refs.verification.insertBefore(this.blockCanvas, this.$refs.slideVerify)
? ? ? let x = this.randomNumber(60, 200)
? ? ? let y = 40
? ? ? this.imgX = x
? ? ? let c = this.$refs.slideVerify
? ? ? let bg = c.getContext('2d')
? ? ? let img = this.$refs.imgs
? ? ? let bk = this.blockCanvas.getContext('2d')
? ? ? // 在兩塊畫布上都放上相同的圖片
? ? ? img.onload = () => {
? ? ? ? bg.drawImage(img, 0, 0)
? ? ? ? bk.drawImage(img, 0, 0)
? ? ? }
? ? ? this.drawBlock(bg, x, y, 'fill')
? ? ? this.drawBlock(bk, x, y, 'clip')
? ? },
? ? // 畫摳出來的方塊
? ? drawBlock (ctx, x, y, type) {
? ? ? ctx.beginPath()
? ? ? ctx.moveTo(x, y)
? ? ? ctx.arc(x + 42 / 2, y - 9 + 2, 9, 0.72 * Math.PI, 2.26 * Math.PI)
? ? ? ctx.lineTo(x + 42, y)
? ? ? ctx.arc(x + 42 + 9 - 2, y + 42 / 2, 9, 1.21 * Math.PI, 2.78 * Math.PI)
? ? ? ctx.lineTo(x + 42, y + 42)
? ? ? ctx.lineTo(x, y + 42)
? ? ? ctx.arc(x + 9 - 2, y + 42 / 2, 9 + 0.4, 2.76 * Math.PI, 1.24 * Math.PI, true)
? ? ? ctx.lineTo(x, y)
? ? ? ctx.lineWidth = 2
? ? ? ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
? ? ? ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
? ? ? ctx.stroke()
? ? ? ctx[type]()
? ? ? ctx.globalCompositeOperation = 'destination-over'
? ? ? // 解決進入頁面時不自動扣拼圖樣式的麻煩(有時需要鼠標點擊后才會出現(xiàn)裁剪后的拼圖)
? ? ? this.blockCanvas.style.left = `-${x}px`
? ? },
? ? // 刷新
? ? refresh () {
? ? ? // 有時會出現(xiàn)點擊刷新,randomNumber返回的數(shù)字和上次存儲的一樣,畫布清空后但是填充時沒有改變;所以當一樣時,不會執(zhí)行刷新操作
? ? ? if (this.imgIndex == this.randomNumber(0, 4)) {
? ? ? ? return false
? ? ? }
? ? ? this.clean()
? ? ? this.$refs.btn.style.left = 0
? ? ? this.$refs.bg.style.width = 0
? ? ? this.$refs.btn.classList.remove('btnsuccess')
? ? ? this.isDown = false // 鼠標是否按下
? ? ? this.btnX = 0 // 鼠標點擊的水平位置與滑塊移動水平位置的差
? ? ? this.imgX = 0
? ? ? this.imageCanvas('restore')
? ? ? this.imgIndex = this.randomNumber(0, 4)
? ? },
? ? // 清空canvas
? ? clean () {
? ? ? let cxt2 = this.$refs.slideVerify.getContext('2d')
? ? ? cxt2.clearRect(0, 0, 300, 150)
? ? },
? ? // 新建canvas
? ? createCanvas (width, height) {
? ? ? const canvas = document.createElement('canvas')
? ? ? canvas.width = width
? ? ? canvas.height = height
? ? ? canvas.style.position = 'absolute'
? ? ? return canvas
? ? }
? }
}
</script>

<style scoped>
.verification {
? position: relative;
? width: 300px;
? margin: 0 auto;
}
.slide-wrapper {
? position: relative;
? width: 300px;
? height: 40px;
}
.bg-start {
? background: cadetblue;
}
.bg {
? position: absolute;
? height: 40px;
? background: #ccc;
}
.text {
? position: absolute;
? width: 100%;
? height: 40px;
? text-align: center;
? line-height: 40px;
? margin: 0;
? /* z-index: 1; */
}
.text-success {
? color: white;
? z-index: 2;
}
.btn {
? position: absolute;
? width: 40px;
? height: 40px;
? z-index: 1;
? border-radius: 5px;
? background: rgb(143, 145, 148);
? text-align: center;
? font-size: 24px;
? color: white;
? box-shadow: 0 0 1px 1px #fff;
? background: #fff no-repeat center url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==");
}
.btnsuccess {
? background: #fff no-repeat center url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==");
}
.refresh {
? ? cursor: pointer;
? ? width: 20px;
? ? height: 20px;
? ? position: absolute;
? ? z-index: 1;
? ? top: 0;
? ? right: 10px;
? ? opacity: .6;
? ? background: url('../assets/ref.jpg') no-repeat;
? ? background-size: cover;
}
</style>

完成效果圖

滑動完成時

因為允許1px的差距,可以自己改

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

相關文章

  • vue使用moment如何將時間戳轉為標準日期時間格式

    vue使用moment如何將時間戳轉為標準日期時間格式

    這篇文章主要介紹了vue使用moment如何將時間戳轉為標準日期時間格式問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Vue組件實現(xiàn)觸底判斷

    Vue組件實現(xiàn)觸底判斷

    這篇文章主要為大家詳細介紹了Vue組件實現(xiàn)觸底判斷,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • 基于vue2.0實現(xiàn)仿百度前端分頁效果附實現(xiàn)代碼

    基于vue2.0實現(xiàn)仿百度前端分頁效果附實現(xiàn)代碼

    本文通過實例代碼給大家介紹了基于vue2.0實現(xiàn)仿百度前端分頁效果,在文中給大家記錄了遇到的問題及解決方法,需要的朋友可以參考下
    2018-10-10
  • Vue3.5中新增的baseWatch函數(shù)用法詳解

    Vue3.5中新增的baseWatch函數(shù)用法詳解

    在Vue 3.5.0-beta.3版本中新增了一個base watch函數(shù),這個函數(shù)用法和我們熟知的watch API一模一樣,下面就跟隨小編一起來了解一下它的具體使用吧
    2024-11-11
  • 詳解Vue2.0配置mint-ui踩過的那些坑

    詳解Vue2.0配置mint-ui踩過的那些坑

    這篇文章主要介紹了詳解Vue2.0配置mint-ui踩過的那些坑,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 用vuex寫了一個購物車H5頁面的示例代碼

    用vuex寫了一個購物車H5頁面的示例代碼

    本篇文章主要介紹了用vuex寫了一個購物車H5頁面的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-12-12
  • vue的指令和插值總結(非常詳細)

    vue的指令和插值總結(非常詳細)

    這篇文章主要給大家介紹了關于vue指令和插值的相關資料,大家應該對指令和插值都不陌生,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • 淺談Vue的響應式原理

    淺談Vue的響應式原理

    讓我們來回顧下Vue的介紹,可以發(fā)現(xiàn)Vue 最顯著的一個功能是響應系統(tǒng)。那么它的實現(xiàn)原理有又是如何呢?下面小編和大家來一起學習一下
    2019-05-05
  • vue打包npm run build時候界面報錯的解決

    vue打包npm run build時候界面報錯的解決

    這篇文章主要介紹了vue打包npm run build時候界面報錯的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • vue結合leaflet實現(xiàn)地圖放大鏡

    vue結合leaflet實現(xiàn)地圖放大鏡

    放大鏡在很多地方都可以使用的到,本文主要介紹了vue結合leaflet實現(xiàn)地圖放大鏡,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06

最新評論

贡觉县| 博罗县| 台中县| 桐庐县| 遂昌县| 泗水县| 鸡西市| 呼伦贝尔市| 陆丰市| 平遥县| 成武县| 安国市| 连江县| 华蓥市| 新绛县| 都匀市| 武义县| 九龙城区| 慈利县| 盱眙县| 酉阳| 沂南县| 长沙县| 马鞍山市| 东兴市| 开平市| 上犹县| 新龙县| 深圳市| 石台县| 九江市| 巩留县| 监利县| 张北县| 甘孜县| 凌海市| 灌阳县| 胶州市| 都匀市| 肥西县| 大新县|